@pygmalionjs/pygmalion 0.6.28 → 0.6.30
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-lib/{FrozenRoutePreview-Xm7o3urC.js → FrozenRoutePreview-D9J35QsM.js} +2842 -2687
- package/dist-lib/pygmalion.js +8304 -7965
- package/dist-lib/testing.js +1 -1
- package/dist-lib/types/App.d.ts +3 -0
- package/dist-lib/types/canvas/ShadowRoutePreview.d.ts +3 -0
- package/dist-lib/types/editor/designCompiler.d.ts +76 -1
- package/dist-lib/types/editor/flowSessions.d.ts +3 -1
- package/dist-lib/types/editor/frameInteraction.d.ts +7 -1
- package/dist-lib/types/editor/interactiveSessionSurface.d.ts +19 -0
- package/dist-lib/types/editor/interactiveStates.d.ts +3 -2
- package/dist-lib/types/editor/previewReachability.d.ts +7 -0
- package/dist-lib/types/editor/store.d.ts +14 -2
- package/dist-lib/types/lib.d.ts +9 -3
- package/dist-lib/types/shell/CodePanel.d.ts +4 -1
- package/docs/screen-state-contract.md +7 -4
- package/node/storyboard-capture-runtime.mjs +50 -0
- package/package.json +1 -1
package/dist-lib/testing.js
CHANGED
package/dist-lib/types/App.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { DesignCodegenProjectManifest } from './editor/designCompiler';
|
|
1
2
|
export interface AppProps {
|
|
2
3
|
/** The route identity is stable enough to read or produce preview artifacts. */
|
|
3
4
|
previewIdentityReady?: boolean;
|
|
5
|
+
/** Checked-in host contract used by repository-aware codegen adapters. */
|
|
6
|
+
codegenProject?: DesignCodegenProjectManifest;
|
|
4
7
|
}
|
|
5
8
|
export declare const App: import("react").FunctionComponent<AppProps>;
|
|
@@ -17,4 +17,7 @@ export declare const ShadowRoutePreview: import("react").FunctionComponent<{
|
|
|
17
17
|
mountPriority?: number;
|
|
18
18
|
onDocumentHeightChange?: (height: number) => void;
|
|
19
19
|
onReplayIssuesChange?: (issues: string[]) => void;
|
|
20
|
+
onReachableTestIdsChange?: (testIds: readonly string[]) => void;
|
|
21
|
+
/** Enables immediate scrolling while the live React document warms. */
|
|
22
|
+
interactionEnabled?: boolean;
|
|
20
23
|
}>;
|
|
@@ -2,6 +2,8 @@ import { type CodegenFrameOptions, type CodegenNode } from './codegen';
|
|
|
2
2
|
import { type NodeJSON } from './store';
|
|
3
3
|
export declare const DESIGN_IR_SCHEMA: "pygmalion.design-ir";
|
|
4
4
|
export declare const DESIGN_IR_VERSION: 1;
|
|
5
|
+
export declare const DESIGN_CODEGEN_PROJECT_SCHEMA: "pygmalion.codegen-project";
|
|
6
|
+
export declare const DESIGN_CODEGEN_PROJECT_VERSION: 1;
|
|
5
7
|
export type DesignCompilePurpose = 'interactive' | 'export';
|
|
6
8
|
export type DesignCompileSeverity = 'info' | 'warning' | 'error';
|
|
7
9
|
export type DesignCompileStage = 'normalize' | 'analyze' | 'generate' | 'resource';
|
|
@@ -43,6 +45,70 @@ export interface DesignIRMetrics {
|
|
|
43
45
|
componentCount: number;
|
|
44
46
|
assetCount: number;
|
|
45
47
|
}
|
|
48
|
+
/** JSON-shaped host data produced from a repository-owned codegen contract. */
|
|
49
|
+
export type DesignCodegenData = null | string | number | boolean | readonly DesignCodegenData[] | {
|
|
50
|
+
readonly [key: string]: DesignCodegenData;
|
|
51
|
+
};
|
|
52
|
+
export interface DesignCodegenPromptReference {
|
|
53
|
+
/** Repository-relative agent instruction file used to author this manifest. */
|
|
54
|
+
sourcePath: string;
|
|
55
|
+
/** Host-owned revision bumped when the instructions or output contract change. */
|
|
56
|
+
revision: string;
|
|
57
|
+
}
|
|
58
|
+
export interface DesignCodegenFrameContract {
|
|
59
|
+
/** Canonical source anchors chosen by the host, in addition to observed files. */
|
|
60
|
+
sourcePaths?: readonly string[];
|
|
61
|
+
/** Adapter-specific, deterministic metadata. It is never interpreted by core. */
|
|
62
|
+
metadata?: Readonly<Record<string, DesignCodegenData>>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Checked-in output of a repository's codegen instructions.
|
|
66
|
+
*
|
|
67
|
+
* The prompt is provenance, not a runtime dependency: adapters consume this
|
|
68
|
+
* manifest synchronously and never call a model while the editor is open.
|
|
69
|
+
*/
|
|
70
|
+
export interface DesignCodegenProjectManifest {
|
|
71
|
+
schema: typeof DESIGN_CODEGEN_PROJECT_SCHEMA;
|
|
72
|
+
version: typeof DESIGN_CODEGEN_PROJECT_VERSION;
|
|
73
|
+
defaultTarget?: string;
|
|
74
|
+
prompt?: DesignCodegenPromptReference;
|
|
75
|
+
frames?: Readonly<Record<string, DesignCodegenFrameContract>>;
|
|
76
|
+
}
|
|
77
|
+
export interface DesignCodegenPageContext {
|
|
78
|
+
/** Canonical import id when available, otherwise the editor-local page id. */
|
|
79
|
+
id: string;
|
|
80
|
+
name: string;
|
|
81
|
+
route?: string;
|
|
82
|
+
previewRoute?: string;
|
|
83
|
+
sourcePaths: readonly string[];
|
|
84
|
+
flow?: string;
|
|
85
|
+
scenario?: string;
|
|
86
|
+
state?: string;
|
|
87
|
+
stateKind?: string;
|
|
88
|
+
scenarioId?: string;
|
|
89
|
+
scenarioIds: readonly string[];
|
|
90
|
+
desiredState?: Readonly<Record<string, DesignCodegenData>>;
|
|
91
|
+
/** Current reproducible recipe; direct state stays separate for easy adapters. */
|
|
92
|
+
capture: {
|
|
93
|
+
environment?: DesignCodegenData;
|
|
94
|
+
preset?: DesignCodegenData;
|
|
95
|
+
interactions: readonly DesignCodegenData[];
|
|
96
|
+
assertions: readonly DesignCodegenData[];
|
|
97
|
+
};
|
|
98
|
+
interactiveStateId?: string;
|
|
99
|
+
interactiveOptionId?: string;
|
|
100
|
+
interactiveOptionIds?: readonly string[];
|
|
101
|
+
viewport: {
|
|
102
|
+
width: number;
|
|
103
|
+
height: number;
|
|
104
|
+
};
|
|
105
|
+
/** Frame-specific checked-in contract selected by id. */
|
|
106
|
+
contract?: DesignCodegenFrameContract;
|
|
107
|
+
}
|
|
108
|
+
export interface DesignCodegenRuntimeContext {
|
|
109
|
+
page?: DesignCodegenPageContext;
|
|
110
|
+
project?: DesignCodegenProjectManifest;
|
|
111
|
+
}
|
|
46
112
|
export interface DesignIntermediateDocumentV1 {
|
|
47
113
|
schema: typeof DESIGN_IR_SCHEMA;
|
|
48
114
|
version: typeof DESIGN_IR_VERSION;
|
|
@@ -61,7 +127,7 @@ export interface DesignCompileLimits {
|
|
|
61
127
|
maxOutputBytes: number;
|
|
62
128
|
}
|
|
63
129
|
export declare const DEFAULT_DESIGN_COMPILE_LIMITS: Readonly<DesignCompileLimits>;
|
|
64
|
-
export interface DesignCodegenAdapterContext {
|
|
130
|
+
export interface DesignCodegenAdapterContext extends DesignCodegenRuntimeContext {
|
|
65
131
|
document: DesignIntermediateDocumentV1;
|
|
66
132
|
}
|
|
67
133
|
export interface DesignCodegenAdapterOutput {
|
|
@@ -73,6 +139,13 @@ export interface DesignCodegenAdapter {
|
|
|
73
139
|
label: string;
|
|
74
140
|
language: string;
|
|
75
141
|
extension: string;
|
|
142
|
+
/**
|
|
143
|
+
* Repository adapters generate from checked-in source contracts rather than
|
|
144
|
+
* approximating the captured design tree. They still receive the document
|
|
145
|
+
* for source-map context, but design-IR warnings and preview size deferral do
|
|
146
|
+
* not describe their output.
|
|
147
|
+
*/
|
|
148
|
+
basis?: 'design-ir' | 'repository';
|
|
76
149
|
generate(context: DesignCodegenAdapterContext): string | DesignCodegenAdapterOutput;
|
|
77
150
|
}
|
|
78
151
|
export interface DesignCompileOptions {
|
|
@@ -81,6 +154,8 @@ export interface DesignCompileOptions {
|
|
|
81
154
|
force?: boolean;
|
|
82
155
|
frame?: CodegenFrameOptions;
|
|
83
156
|
limits?: Partial<DesignCompileLimits>;
|
|
157
|
+
/** Current repository frame and checked-in codegen contract for host adapters. */
|
|
158
|
+
context?: DesignCodegenRuntimeContext;
|
|
84
159
|
}
|
|
85
160
|
export interface DesignCompileResult {
|
|
86
161
|
target: string;
|
|
@@ -144,7 +144,9 @@ export declare const __flowSessionWarmDebug: {
|
|
|
144
144
|
bootsByRunner: Record<string, number>;
|
|
145
145
|
};
|
|
146
146
|
/** Drops parked instances globally, or only those owned by one runner. */
|
|
147
|
-
export declare function evictFlowSessionWarmInstances(ownerLabel?: string
|
|
147
|
+
export declare function evictFlowSessionWarmInstances(ownerLabel?: string, options?: {
|
|
148
|
+
preservePinned?: boolean;
|
|
149
|
+
}): void;
|
|
148
150
|
/**
|
|
149
151
|
* True when a walk of this path would resume on a parked instance. Activation
|
|
150
152
|
* warming reads it to decide whether the frame already has a resumable
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FrameInteractionPhase = 'idle' | 'starting' | 'interacting';
|
|
1
|
+
export type FrameInteractionPhase = 'idle' | 'starting' | 'preview' | 'interacting';
|
|
2
2
|
export interface FrameInteractionScrollState {
|
|
3
3
|
x: number;
|
|
4
4
|
y: number;
|
|
@@ -51,6 +51,12 @@ export declare function subscribeFrameInteraction(listener: () => void): () => v
|
|
|
51
51
|
* without learning whether the running surface is an iframe or another host.
|
|
52
52
|
*/
|
|
53
53
|
export declare function connectFrameInteractionViewport(frameId: string, adapter: FrameInteractionViewportAdapter): () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Makes the frozen DOM useful immediately while its live React document warms.
|
|
56
|
+
* The preview is a scroll-only bridge: navigation and form submission stay
|
|
57
|
+
* contained, and the live iframe later replaces it without ending the session.
|
|
58
|
+
*/
|
|
59
|
+
export declare function connectFrameInteractionPreview(frameId: string, root: ShadowRoot, contentElement: HTMLElement): () => void;
|
|
54
60
|
/** Scrolls the running frame viewport and immediately republishes its reading. */
|
|
55
61
|
export declare function setFrameInteractionScroll(position: {
|
|
56
62
|
x?: number;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* published, while the active frame may mirror the running document
|
|
7
7
|
* immediately so capture stability never becomes interaction latency.
|
|
8
8
|
*/
|
|
9
|
+
import type { DesignScreenDesiredState } from './designImport';
|
|
9
10
|
export interface InteractiveSessionSurface {
|
|
10
11
|
iframe: HTMLIFrameElement;
|
|
11
12
|
screenId: string;
|
|
@@ -19,8 +20,26 @@ export declare function directInteractiveSessionSurfaceId(pageId: string, stateI
|
|
|
19
20
|
export declare function setDirectInteractiveStateRequestHandler(handler: ((pageId: string) => void) | null): void;
|
|
20
21
|
/** Starts direct-state delivery in the same task as the right-panel click. */
|
|
21
22
|
export declare function requestDirectInteractiveState(pageId: string): boolean;
|
|
23
|
+
/** Installs the paint-first path used before the observable page recipe changes. */
|
|
24
|
+
export declare function setDirectInteractiveStatePreviewHandler(handler: ((request: {
|
|
25
|
+
pageId: string;
|
|
26
|
+
stateId: string;
|
|
27
|
+
desiredState: DesignScreenDesiredState;
|
|
28
|
+
}) => boolean) | null): void;
|
|
29
|
+
/** Applies a direct host state without invalidating the editor model yet. */
|
|
30
|
+
export declare function requestDirectInteractiveStatePreview(request: {
|
|
31
|
+
pageId: string;
|
|
32
|
+
stateId: string;
|
|
33
|
+
desiredState: DesignScreenDesiredState;
|
|
34
|
+
}): boolean;
|
|
22
35
|
/** Exposes a runner-owned iframe without transferring its ownership. */
|
|
23
36
|
export declare function exposeInteractiveSessionSurface(screenId: string, iframe: HTMLIFrameElement): void;
|
|
37
|
+
/**
|
|
38
|
+
* Hands an in-flight prewarm slot to the frame that has just exposed its axis.
|
|
39
|
+
* If preparation has not presented the iframe yet, its first exposure follows
|
|
40
|
+
* the redirect instead of landing in the now-private staging slot.
|
|
41
|
+
*/
|
|
42
|
+
export declare function redirectInteractiveSessionSurface(fromScreenId: string, toScreenId: string): boolean;
|
|
24
43
|
/** Releases a surface only when the caller still owns the registered iframe. */
|
|
25
44
|
export declare function releaseInteractiveSessionSurface(screenId: string, iframe: HTMLIFrameElement): void;
|
|
26
45
|
/** Clears a presentation slot when its page returns to an authored state. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DesignScreenInteraction, DesignSerializable, StoryboardEnvironment } from './designImport';
|
|
2
2
|
import type { PageModel } from './store';
|
|
3
|
+
export { reachablePreviewTestIds } from './previewReachability';
|
|
3
4
|
/**
|
|
4
5
|
* Screen-state axes — same-frame variations reproduced by a gesture or a boot
|
|
5
6
|
* condition.
|
|
@@ -136,10 +137,10 @@ export declare function validateInteractiveStates(defs: readonly InteractiveStat
|
|
|
136
137
|
/** Validates both interaction and condition axes. */
|
|
137
138
|
export declare const validateScreenStateAxes: typeof validateInteractiveStates;
|
|
138
139
|
/** Reads only the control-presence evidence needed by the view-only inspector. */
|
|
139
|
-
export declare function previewMarkupTestIds(markup: string | null | undefined): readonly string[];
|
|
140
|
+
export declare function previewMarkupTestIds(markup: string | null | undefined, bodyAttributes?: string | null): readonly string[];
|
|
140
141
|
/**
|
|
141
142
|
* Axes available on one frame. The test-id requirement is checked against
|
|
142
|
-
* either the imported tree or the frozen preview's
|
|
143
|
+
* either the imported tree or the frozen preview's reachable test-id index.
|
|
143
144
|
* View-only can therefore offer a real screen control without importing the
|
|
144
145
|
* whole layer tree, while a frame without that control still hides the axis.
|
|
145
146
|
*/
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const REACHABLE_TEST_IDS_ATTRIBUTE = "data-pygmalion-reachable-testids";
|
|
2
|
+
/** Test ids whose rendered controls can actually be reached from this frame. */
|
|
3
|
+
export declare function reachablePreviewTestIds(root: ParentNode): readonly string[];
|
|
4
|
+
/** Stamps capture-time reachability without mutating the running document. */
|
|
5
|
+
export declare function stampReachablePreviewTestIds(source: Document, clone: HTMLElement): void;
|
|
6
|
+
/** Reads a capture-time reachability index, or null for a legacy snapshot. */
|
|
7
|
+
export declare function indexedReachablePreviewTestIds(markup: string): readonly string[] | null;
|
|
@@ -221,6 +221,12 @@ export interface PageModel {
|
|
|
221
221
|
interactiveStateId?: string;
|
|
222
222
|
/** The active option is rendered through host desired state, without replay. */
|
|
223
223
|
interactiveStateUsesDesiredState?: boolean;
|
|
224
|
+
/**
|
|
225
|
+
* Imported layers still showing behind a direct live surface. The surface
|
|
226
|
+
* paints first; FrameView consumes this key and invalidates the old layers
|
|
227
|
+
* on the following frame so a large tree cannot block the visible switch.
|
|
228
|
+
*/
|
|
229
|
+
interactiveLayerRefreshKey?: string;
|
|
224
230
|
interactiveOptionId?: string;
|
|
225
231
|
/**
|
|
226
232
|
* Options held together on a combining axis (InteractiveStateDef.multiple).
|
|
@@ -260,7 +266,7 @@ export interface PageModel {
|
|
|
260
266
|
assertions?: DesignScreenAssertion[];
|
|
261
267
|
/** Host-declared warm instance group. Set when the screen state is declared, not replayed. */
|
|
262
268
|
session?: string;
|
|
263
|
-
/**
|
|
269
|
+
/** Reachable test ids observed in the frozen preview before editable layers are imported. */
|
|
264
270
|
previewTestIds?: readonly string[];
|
|
265
271
|
layerImportCount?: number;
|
|
266
272
|
layerImportTruncated?: boolean;
|
|
@@ -467,6 +473,8 @@ export declare class EditorStore {
|
|
|
467
473
|
private pageEditRevisions;
|
|
468
474
|
/** pageId → edit revision at the moment a frozen preview was promoted without a boot (D2). */
|
|
469
475
|
private provisionalLayerImports;
|
|
476
|
+
/** Latest paint-first direct-state commit scheduled for each page. */
|
|
477
|
+
private directStateCommitRevisions;
|
|
470
478
|
/** pageId → source geometry awaiting its post-mount fidelity measurement. */
|
|
471
479
|
private pendingLayerImportGeometry;
|
|
472
480
|
/** View-only motion playback never becomes part of a frame recipe or undo history. */
|
|
@@ -737,7 +745,11 @@ export declare class EditorStore {
|
|
|
737
745
|
* Pure-CSS pseudo options short-circuit through the held-pseudo fast path
|
|
738
746
|
* (applyHeldPseudoInteractiveState) and never touch the recipe.
|
|
739
747
|
*/
|
|
740
|
-
applyInteractiveState(pageId: string, def: InteractiveStateDef, optionId: string
|
|
748
|
+
applyInteractiveState(pageId: string, def: InteractiveStateDef, optionId: string, options?: {
|
|
749
|
+
skipPaintFirstPreview?: boolean;
|
|
750
|
+
}): boolean;
|
|
751
|
+
/** Invalidates retained layers only after their direct live replacement painted. */
|
|
752
|
+
commitInteractiveLayerRefresh(pageId: string, refreshKey: string): boolean;
|
|
741
753
|
/** The root viewport endpoint currently preserved in this frame recipe. */
|
|
742
754
|
frameScrollRecipe(pageId: string): Readonly<{
|
|
743
755
|
x: number;
|
package/dist-lib/types/lib.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type { StoryboardDefinition } from './editor/storyboardGraph';
|
|
|
18
18
|
import { type TokenDef } from './editor/tokens';
|
|
19
19
|
import { type ViewportPresetDef } from './editor/viewportPresets';
|
|
20
20
|
import { type PreviewEnvironmentControlDef } from './editor/previewEnvironmentControls';
|
|
21
|
+
import type { DesignCodegenProjectManifest } from './editor/designCompiler';
|
|
21
22
|
|
|
22
23
|
export { setComponentRegistry } from './editor/registry';
|
|
23
24
|
export { PYGMALION_PREVIEW_CAPTURE_PROGRESS_SUFFIX, previewCaptureProgressEndpoint, usePygmalionPreviewCaptureProgress, } from './editor/previewCaptureProgress';
|
|
@@ -27,8 +28,8 @@ export type { FrameInteractionPhase, FrameInteractionScrollState, FrameInteracti
|
|
|
27
28
|
export type { ComponentRegistry, RegistryEntry, RegistryPropValue, } from './editor/registry';
|
|
28
29
|
export { enumerateDesignComponentConnectionCases, getDesignComponentConnection, getDesignComponentConnectionForComponent, getDesignComponentConnections, setDesignComponentConnections, validateDesignComponentConnections, } from './editor/componentConnections';
|
|
29
30
|
export type { DesignComponentConnectionCase, DesignComponentConnectionCases, DesignComponentConnectionDef, DesignComponentReference, DesignConnectionDiagnostic, DesignConnectionPropertyDef, DesignConnectionPropertyKind, } from './editor/componentConnections';
|
|
30
|
-
export { compileDesignDocument, createDesignIntermediateDocument, DEFAULT_DESIGN_COMPILE_LIMITS, DESIGN_IR_SCHEMA, DESIGN_IR_VERSION, getDesignCodegenAdapters, registerDesignCodegenAdapter, } from './editor/designCompiler';
|
|
31
|
-
export type { DesignCodegenAdapter, DesignCodegenAdapterContext, DesignCodegenAdapterOutput, DesignCompileDiagnostic, DesignCompileLimits, DesignCompileOptions, DesignCompilePurpose, DesignCompileResult, DesignCompileSeverity, DesignCompileStage, DesignCompileStatus, DesignIntermediateDocumentV1, DesignIRAsset, DesignIRComponent, DesignIRMetrics, } from './editor/designCompiler';
|
|
31
|
+
export { compileDesignDocument, createDesignIntermediateDocument, DEFAULT_DESIGN_COMPILE_LIMITS, DESIGN_CODEGEN_PROJECT_SCHEMA, DESIGN_CODEGEN_PROJECT_VERSION, DESIGN_IR_SCHEMA, DESIGN_IR_VERSION, getDesignCodegenAdapters, registerDesignCodegenAdapter, } from './editor/designCompiler';
|
|
32
|
+
export type { DesignCodegenAdapter, DesignCodegenAdapterContext, DesignCodegenAdapterOutput, DesignCodegenData, DesignCodegenFrameContract, DesignCodegenPageContext, DesignCodegenProjectManifest, DesignCodegenPromptReference, DesignCodegenRuntimeContext, DesignCompileDiagnostic, DesignCompileLimits, DesignCompileOptions, DesignCompilePurpose, DesignCompileResult, DesignCompileSeverity, DesignCompileStage, DesignCompileStatus, DesignIntermediateDocumentV1, DesignIRAsset, DesignIRComponent, DesignIRMetrics, } from './editor/designCompiler';
|
|
32
33
|
export type { CodegenFrameOptions } from './editor/codegen';
|
|
33
34
|
export { createDesignComponentCatalog, createDesignComponentVariantMatrix, createDesignGalleryCatalog, designCatalogKey, designCatalogRegistryName, PygmalionCatalogDocument, PygmalionCatalogMatrix, PygmalionCatalogSection, } from './editor/catalog';
|
|
34
35
|
export type { DesignCatalogBuild, DesignCatalogFrame, DesignCatalogItem, DesignCatalogKind, DesignCatalogPageDescriptor, DesignComponentCatalogOptions, DesignComponentVariantMatrix, DesignGalleryCatalogOptions, PygmalionCatalogDocumentProps, PygmalionCatalogMatrixProps, PygmalionCatalogSectionProps, } from './editor/catalog';
|
|
@@ -281,7 +282,7 @@ export declare function pygmalionOpenPreview(): void;
|
|
|
281
282
|
export declare function pygmalionResetCurrentEdits(): boolean;
|
|
282
283
|
export interface InitialPageDef extends DesignImportInitialPage {
|
|
283
284
|
}
|
|
284
|
-
export declare function PygmalionEditor({ registry, tokens, initialPages, initialCanvas, initialEditMode, componentConnections, viewportPresets, sessionPresets, previewEnvironmentControls, designImport, onTokensChange, appOrigin, previewRevision, previewCacheNamespace, previewArtifacts, previewArtifactEndpoint, previewConcurrency, previewOpen, onPreviewOpenChange, flowCanvas, frameSurface, captureSupply, screenFlows, screenFlowConcurrency, scenarioCoverage, screenDimensions, screenLists, sectionHeaders, sectionHeaderLabels, screenLanes, frameBranchKinds, frameLabelLabels, screenCards, liveScreenBudget, screenStateAxes, interactiveStates, surfaceClassifications, onApply, onDesignChange, onInspectApply, onInspectPreview, onInspectImpact, storyboard, storyboardScenarios, sessionStoryboards, storyboardDiscovery, storyboardDiscoveryEndpoint, }: {
|
|
285
|
+
export declare function PygmalionEditor({ registry, tokens, initialPages, initialCanvas, initialEditMode, componentConnections, codegenProject, viewportPresets, sessionPresets, previewEnvironmentControls, designImport, onTokensChange, appOrigin, previewRevision, previewCacheNamespace, previewArtifacts, previewArtifactEndpoint, previewConcurrency, previewOpen, onPreviewOpenChange, flowCanvas, frameSurface, captureSupply, screenFlows, screenFlowConcurrency, scenarioCoverage, screenDimensions, screenLists, sectionHeaders, sectionHeaderLabels, screenLanes, frameBranchKinds, frameLabelLabels, screenCards, liveScreenBudget, screenStateAxes, interactiveStates, surfaceClassifications, onApply, onDesignChange, onInspectApply, onInspectPreview, onInspectImpact, storyboard, storyboardScenarios, sessionStoryboards, storyboardDiscovery, storyboardDiscoveryEndpoint, }: {
|
|
285
286
|
registry?: ComponentRegistry;
|
|
286
287
|
tokens?: TokenDef[];
|
|
287
288
|
initialPages?: InitialPageDef[];
|
|
@@ -296,6 +297,11 @@ export declare function PygmalionEditor({ registry, tokens, initialPages, initia
|
|
|
296
297
|
initialEditMode?: 'edit' | 'view-only';
|
|
297
298
|
/** Explicit external-design to registered-code component mappings. */
|
|
298
299
|
componentConnections?: readonly DesignComponentConnectionDef[];
|
|
300
|
+
/**
|
|
301
|
+
* Checked-in repository contract for deterministic, state-aware codegen.
|
|
302
|
+
* Its prompt reference is provenance only; no model runs in the editor.
|
|
303
|
+
*/
|
|
304
|
+
codegenProject?: DesignCodegenProjectManifest;
|
|
299
305
|
/** Named frame widths the application supports — rendered as one-click buttons beside the W/H boxes. */
|
|
300
306
|
viewportPresets?: readonly ViewportPresetDef[];
|
|
301
307
|
/**
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { type DesignCodegenProjectManifest } from '../editor/designCompiler';
|
|
2
|
+
export declare const CodePanel: import("react").FunctionComponent<{
|
|
3
|
+
codegenProject?: DesignCodegenProjectManifest;
|
|
4
|
+
}>;
|
|
@@ -75,10 +75,13 @@ automatic duplicate. Click-driven toggles and other application states remain
|
|
|
75
75
|
declared axes unless they already have their own review frame.
|
|
76
76
|
|
|
77
77
|
In view-only mode, `requires.testId` is matched against the frozen preview's
|
|
78
|
-
lightweight test-id index as well as an imported layer tree.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
lightweight **reachable** test-id index as well as an imported layer tree. A
|
|
79
|
+
test id under `display: none`, hidden visibility, zero opacity, or an inert
|
|
80
|
+
ancestor does not qualify merely because React kept that branch mounted. This
|
|
81
|
+
keeps right-panel state controls available without turning selection into a
|
|
82
|
+
layer import or live boot, while hiding axes that the captured frame cannot
|
|
83
|
+
actually reach. Legacy snapshots without a capture-time index are measured
|
|
84
|
+
after their inert DOM mounts.
|
|
82
85
|
|
|
83
86
|
## Automatic motion coverage
|
|
84
87
|
|
|
@@ -1056,6 +1056,56 @@ export function serializeStoryboardPreviewDocument(
|
|
|
1056
1056
|
const clone = document.documentElement.cloneNode(true);
|
|
1057
1057
|
if (!(clone instanceof HTMLElement)) return null;
|
|
1058
1058
|
|
|
1059
|
+
// A frozen snapshot preserves branches that are mounted but visually absent
|
|
1060
|
+
// (for example, two workspace panels cross-faded with opacity). Presence
|
|
1061
|
+
// alone therefore cannot tell the inspector which controls this captured
|
|
1062
|
+
// frame can actually reach. Record a compact, capture-time visibility index
|
|
1063
|
+
// on the body; older snapshots without it are measured again after mount.
|
|
1064
|
+
try {
|
|
1065
|
+
const reachableTestIds = new Set();
|
|
1066
|
+
const hasRenderedBox = (element) => {
|
|
1067
|
+
const rect = element.getBoundingClientRect();
|
|
1068
|
+
if (rect.width > 0 && rect.height > 0) return true;
|
|
1069
|
+
return [...element.querySelectorAll('*')].some((descendant) => {
|
|
1070
|
+
const descendantRect = descendant.getBoundingClientRect();
|
|
1071
|
+
return descendantRect.width > 0 && descendantRect.height > 0;
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
const isReachable = (element) => {
|
|
1075
|
+
for (
|
|
1076
|
+
let current = element;
|
|
1077
|
+
current;
|
|
1078
|
+
current = current.parentElement
|
|
1079
|
+
) {
|
|
1080
|
+
const style = window.getComputedStyle(current);
|
|
1081
|
+
const opacity = Number.parseFloat(style.opacity || '1');
|
|
1082
|
+
if (
|
|
1083
|
+
current.hasAttribute('hidden') ||
|
|
1084
|
+
current.hasAttribute('inert') ||
|
|
1085
|
+
style.display === 'none' ||
|
|
1086
|
+
style.visibility === 'hidden' ||
|
|
1087
|
+
style.visibility === 'collapse' ||
|
|
1088
|
+
(Number.isFinite(opacity) && opacity <= 0)
|
|
1089
|
+
) {
|
|
1090
|
+
return false;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
return hasRenderedBox(element);
|
|
1094
|
+
};
|
|
1095
|
+
for (const element of document.documentElement.querySelectorAll('*')) {
|
|
1096
|
+
const testId = element.getAttribute('data-testid');
|
|
1097
|
+
if (testId && isReachable(element)) reachableTestIds.add(testId);
|
|
1098
|
+
}
|
|
1099
|
+
const cloneBody = clone.querySelector('body');
|
|
1100
|
+
cloneBody?.setAttribute(
|
|
1101
|
+
'data-pygmalion-reachable-testids',
|
|
1102
|
+
encodeURIComponent(JSON.stringify([...reachableTestIds].sort())),
|
|
1103
|
+
);
|
|
1104
|
+
} catch {
|
|
1105
|
+
// Reachability metadata is additive. A constrained capture realm may not
|
|
1106
|
+
// implement layout; the mounted-preview fallback handles that snapshot.
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1059
1109
|
const sourceInputs = [...document.querySelectorAll('input')];
|
|
1060
1110
|
const cloneInputs = [...clone.querySelectorAll('input')];
|
|
1061
1111
|
sourceInputs.forEach((source, index) => {
|