@pygmalionjs/pygmalion 0.11.0 → 0.12.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.
@@ -22,7 +22,7 @@ export interface PasteDesignResult {
22
22
  nodeIds: Record<string, string>;
23
23
  }
24
24
  /** Pure paste plan; commit the returned same-identity snapshot as one undoable transaction. */
25
- export declare function pasteDesignSubtrees(target: DesignDocument, payload: DesignClipboard, options: {
25
+ export declare function pasteDesignSubtrees(targetInput: DesignDocument, payloadInput: DesignClipboard, options: {
26
26
  parentId: string;
27
27
  allocateId: (sourceId: string) => string;
28
28
  offset?: {
@@ -4,6 +4,8 @@ import type { DesignDocument, DocumentNode, DocumentResolveOptions } from '../..
4
4
  export interface ProjectedDocumentNode {
5
5
  sourceNodeId: string;
6
6
  instanceId?: string;
7
+ /** Runtime presentation may attach the canonical enclosing instance path. */
8
+ instancePath?: readonly string[];
7
9
  rowPath: BindingRuntimeScope['rowPath'];
8
10
  node: DocumentNode;
9
11
  children: ProjectedDocumentNode[];
@@ -0,0 +1,5 @@
1
+ import type { PrototypeMotionLayer } from '../../document/prototypeMotion.js';
2
+ /** Collect both incoming and inert outgoing scenes without traversing outside the supplied scene.
3
+ * Legacy renderers can recover kinds from their source document. Unresolved or malformed
4
+ * identities remain invalid descriptors so they crossfade without being paired. */
5
+ export declare function collectPrototypeMotionLayers(scene: HTMLElement, resolveKind?: (sourceNodeId: string) => string | undefined): PrototypeMotionLayer<HTMLElement>[];
@@ -1,5 +1,6 @@
1
1
  import type { DesignDocument, DocumentNode, ResolvedDocumentNode } from '../../document/contracts.js';
2
2
  import { type PrototypeEffect, type PrototypeEvent, type PrototypeRuntimeContext, type PrototypeStartOptions, type PrototypeState } from '../../document/prototype.js';
3
+ import { type PrototypeDragFinishInput, type PrototypeDragStartInput } from '../../document/prototypeDrag.js';
3
4
  export interface PrototypeClock {
4
5
  now(): number;
5
6
  schedule(callback: () => void, delayMs: number): unknown;
@@ -10,6 +11,13 @@ export interface PrototypePlayerSnapshot {
10
11
  previous: PrototypeState | null;
11
12
  effects: readonly PrototypeEffect[];
12
13
  playing: boolean;
14
+ drag: {
15
+ id: number;
16
+ phase: 'dragging' | 'settling';
17
+ progress: number;
18
+ velocity: number;
19
+ outcome: 'commit' | 'cancel' | null;
20
+ } | null;
13
21
  }
14
22
  export interface PrototypePlayerOptions extends PrototypeStartOptions {
15
23
  clock: PrototypeClock;
@@ -20,6 +28,9 @@ export interface PrototypePlayerController {
20
28
  getSnapshot(): PrototypePlayerSnapshot;
21
29
  subscribe(listener: () => void): () => void;
22
30
  dispatch(event: PrototypeEvent): void;
31
+ beginDrag(input: Omit<PrototypeDragStartInput, 'now'>): boolean;
32
+ updateDrag(input: Pick<PrototypeDragStartInput, 'pointerId' | 'point'>): void;
33
+ endDrag(input: Omit<PrototypeDragFinishInput, 'now'>): void;
23
34
  pause(): void;
24
35
  resume(): void;
25
36
  dispose(): void;
@@ -8,6 +8,9 @@ export interface ReconcileSourceProjection { anchors: JsxStructureAnchor[]; node
8
8
  export interface JsxSourceReconcilerOptions {
9
9
  file: string;
10
10
  identityFile: string;
11
+ /** Additional nullable inputs, captured at construction. Each requires an own input key and proof on both sides.
12
+ * Names must be unique, nonblank, and different from file. identityFile is always included and may appear once. Default: []. */
13
+ optionalInputFiles?: readonly string[];
11
14
  rootId: string;
12
15
  definitionId: string;
13
16
  screenId: string;
@@ -19,7 +19,7 @@ const sourceLayout = layout => layout ? { direction: layout.direction, gap: layo
19
19
  export function createJsxSourceReconciler({
20
20
  file, identityFile, rootId, definitionId, screenId, documentId, opaqueNodeIds,
21
21
  projectSource, resolveWrapper = () => undefined, compileDocumentSource,
22
- allowUnchangedIslandRelocation = false,
22
+ allowUnchangedIslandRelocation = false, optionalInputFiles = [],
23
23
  }) {
24
24
  if ([file, identityFile, rootId, definitionId, screenId, documentId].some(value => typeof value !== 'string' || !value)
25
25
  || file === identityFile || !Array.isArray(opaqueNodeIds) || new Set(opaqueNodeIds).size !== opaqueNodeIds.length
@@ -27,13 +27,19 @@ export function createJsxSourceReconciler({
27
27
  || ![projectSource, resolveWrapper, compileDocumentSource].every(value => typeof value === 'function')) {
28
28
  throw new TypeError('A source reconciler requires explicit files, node identities, and projection/compiler callbacks.');
29
29
  }
30
+ const optionalInputs = Array.isArray(optionalInputFiles) ? [...optionalInputFiles] : null;
31
+ if (!optionalInputs || new Set(optionalInputs).size !== optionalInputs.length
32
+ || optionalInputs.some(value => typeof value !== 'string' || !value.trim() || value === file)) {
33
+ throw new TypeError('Optional source inputs must be unique nonempty file names excluding the main source file.');
34
+ }
35
+ const nullableInputs = new Set([identityFile, ...optionalInputs]);
30
36
  opaqueNodeIds = [...opaqueNodeIds];
31
37
  function capturedInputs(value) {
32
- if (!record(value) || Object.keys(value).length > 500 || !Object.hasOwn(value, identityFile)
33
- || typeof value[file] !== 'string' || !value[file]) fail('inputs-invalid', 'Complete source and identity inputs are required.');
38
+ if (!record(value) || Object.keys(value).length > 500 || [...nullableInputs].some(inputFile => !Object.hasOwn(value, inputFile))
39
+ || typeof value[file] !== 'string' || !value[file]) fail('inputs-invalid', 'Complete source, identity, and declared optional inputs are required.');
34
40
  let size = 0;
35
41
  for (const [inputFile, content] of Object.entries(value)) {
36
- if (content === null && inputFile === identityFile) continue;
42
+ if (content === null && nullableInputs.has(inputFile)) continue;
37
43
  if (typeof content !== 'string' || Buffer.from(content).toString('utf8') !== content) fail('inputs-invalid', 'Source inputs must be UTF-8 strings.', inputFile);
38
44
  size += Buffer.byteLength(content);
39
45
  }
@@ -92,7 +98,9 @@ export function createJsxSourceReconciler({
92
98
  }
93
99
  seen.add(proof.file);
94
100
  }
95
- if (!seen.has(file) || !seen.has(identityFile)) fail('proofs-invalid', 'Source and identity proofs are both required.');
101
+ if (!seen.has(file) || [...nullableInputs].some(inputFile => !seen.has(inputFile))) {
102
+ fail('proofs-invalid', 'Source, identity, and declared optional input proofs are required.');
103
+ }
96
104
  }
97
105
  function verifyProjection(document, projection) {
98
106
  for (const node of projection.nodes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pygmalionjs/pygmalion",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Code-backed DOM design sandbox and visual QA editor",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {