@pygmalionjs/pygmalion 0.8.1 → 0.9.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.
Files changed (129) hide show
  1. package/binding-source.d.ts +25 -0
  2. package/dist-lib/{CameraLayer-B2D29VXQ.js → CameraLayer-BdOko8XE.js} +17 -17
  3. package/dist-lib/pygmalion.js +24599 -12746
  4. package/dist-lib/{runtime-BAy8W1mJ.js → runtime-Dxb-IaLN.js} +12414 -11114
  5. package/dist-lib/style.css +1 -1
  6. package/dist-lib/testing.js +10 -10
  7. package/dist-lib/types/binding/catalog.d.ts +10 -0
  8. package/dist-lib/types/binding/contracts.d.ts +202 -0
  9. package/dist-lib/types/binding/documentCommands.d.ts +38 -0
  10. package/dist-lib/types/binding/index.d.ts +6 -0
  11. package/dist-lib/types/binding/preview.d.ts +37 -0
  12. package/dist-lib/types/binding/source.d.ts +109 -0
  13. package/dist-lib/types/binding/useDataProjection.d.ts +9 -0
  14. package/dist-lib/types/binding/validate.d.ts +8 -0
  15. package/dist-lib/types/core/runtime.d.ts +6 -0
  16. package/dist-lib/types/document/appearance.d.ts +112 -0
  17. package/dist-lib/types/document/assets.d.ts +204 -0
  18. package/dist-lib/types/document/components.d.ts +169 -0
  19. package/dist-lib/types/document/contracts.d.ts +171 -0
  20. package/dist-lib/types/document/engine.d.ts +20 -0
  21. package/dist-lib/types/document/exportSettings.d.ts +45 -0
  22. package/dist-lib/types/document/geometry.d.ts +11 -0
  23. package/dist-lib/types/document/layout.d.ts +53 -0
  24. package/dist-lib/types/document/prototype.d.ts +424 -0
  25. package/dist-lib/types/document/prototypeReferences.d.ts +3 -0
  26. package/dist-lib/types/document/richText.d.ts +185 -0
  27. package/dist-lib/types/document/styles.d.ts +216 -0
  28. package/dist-lib/types/document/svgImport.d.ts +17 -0
  29. package/dist-lib/types/document/vector.d.ts +222 -0
  30. package/dist-lib/types/editor/designCompiler.d.ts +7 -0
  31. package/dist-lib/types/editor/designImport.d.ts +7 -0
  32. package/dist-lib/types/editor/inspect.d.ts +8 -0
  33. package/dist-lib/types/editor/revisionCatalogInstall.d.ts +1 -1
  34. package/dist-lib/types/editor/screenInteractions.d.ts +3 -3
  35. package/dist-lib/types/editor/store.d.ts +1 -1
  36. package/dist-lib/types/host/project.d.ts +44 -0
  37. package/dist-lib/types/host/registryConnections.d.ts +11 -0
  38. package/dist-lib/types/host/sourceFilePlan.d.ts +15 -0
  39. package/dist-lib/types/host/sourceWriteback.d.ts +50 -0
  40. package/dist-lib/types/lib.d.ts +101 -3
  41. package/dist-lib/types/token-library/bindings.d.ts +62 -0
  42. package/dist-lib/types/token-library/contracts.d.ts +117 -0
  43. package/dist-lib/types/token-library/engine.d.ts +13 -0
  44. package/dist-lib/types/workspace/WorkspaceShell.d.ts +9 -0
  45. package/dist-lib/types/workspace/application/ApplicationWorkspace.d.ts +3 -0
  46. package/dist-lib/types/workspace/configuration.d.ts +39 -0
  47. package/dist-lib/types/workspace/contracts.d.ts +64 -0
  48. package/dist-lib/types/workspace/controller.d.ts +35 -0
  49. package/dist-lib/types/workspace/documentSessions.d.ts +42 -0
  50. package/dist-lib/types/workspace/edit/AppearancePanel.d.ts +23 -0
  51. package/dist-lib/types/workspace/edit/ArrangeLayers.d.ts +10 -0
  52. package/dist-lib/types/workspace/edit/AssetsPanel.d.ts +16 -0
  53. package/dist-lib/types/workspace/edit/CanvasGuides.d.ts +19 -0
  54. package/dist-lib/types/workspace/edit/ComponentPanel.d.ts +11 -0
  55. package/dist-lib/types/workspace/edit/DataPanel.d.ts +16 -0
  56. package/dist-lib/types/workspace/edit/DesignWorkspace.d.ts +10 -0
  57. package/dist-lib/types/workspace/edit/LayerTree.d.ts +14 -0
  58. package/dist-lib/types/workspace/edit/LayoutPanel.d.ts +13 -0
  59. package/dist-lib/types/workspace/edit/PrototypePanel.d.ts +12 -0
  60. package/dist-lib/types/workspace/edit/ScopeTransferDialog.d.ts +40 -0
  61. package/dist-lib/types/workspace/edit/SelectionHandles.d.ts +52 -0
  62. package/dist-lib/types/workspace/edit/StylesPanel.d.ts +8 -0
  63. package/dist-lib/types/workspace/edit/TextEditor.d.ts +50 -0
  64. package/dist-lib/types/workspace/edit/VectorEditor.d.ts +89 -0
  65. package/dist-lib/types/workspace/edit/VectorToolbar.d.ts +5 -0
  66. package/dist-lib/types/workspace/edit/canvasGuideModel.d.ts +102 -0
  67. package/dist-lib/types/workspace/edit/clipboard.d.ts +35 -0
  68. package/dist-lib/types/workspace/edit/duplicateMetadata.d.ts +2 -0
  69. package/dist-lib/types/workspace/edit/geometryHandles.d.ts +224 -0
  70. package/dist-lib/types/workspace/edit/layerArrangement.d.ts +39 -0
  71. package/dist-lib/types/workspace/edit/layerMoves.d.ts +44 -0
  72. package/dist-lib/types/workspace/edit/projection.d.ts +12 -0
  73. package/dist-lib/types/workspace/edit/scopeTransfer.d.ts +96 -0
  74. package/dist-lib/types/workspace/edit/textStyles.d.ts +75 -0
  75. package/dist-lib/types/workspace/edit/vectorTools.d.ts +136 -0
  76. package/dist-lib/types/workspace/legacyModeAdapter.d.ts +13 -0
  77. package/dist-lib/types/workspace/source/ResponsiveLayoutPanel.d.ts +20 -0
  78. package/dist-lib/types/workspace/source/SourceReview.d.ts +11 -0
  79. package/dist-lib/types/workspace/source/appearanceSource.d.ts +19 -0
  80. package/dist-lib/types/workspace/source/compiler.d.ts +5 -0
  81. package/dist-lib/types/workspace/source/contracts.d.ts +156 -0
  82. package/dist-lib/types/workspace/source/controller.d.ts +50 -0
  83. package/dist-lib/types/workspace/source/documentRevision.d.ts +2 -0
  84. package/dist-lib/types/workspace/source/draftPreviewClient.d.ts +13 -0
  85. package/dist-lib/types/workspace/source/draftRecipe.d.ts +30 -0
  86. package/dist-lib/types/workspace/source/flowContracts.d.ts +72 -0
  87. package/dist-lib/types/workspace/source/prototypeSource.d.ts +4 -0
  88. package/dist-lib/types/workspace/source/responsive.d.ts +13 -0
  89. package/dist-lib/types/workspace/source/responsiveContracts.d.ts +78 -0
  90. package/dist-lib/types/workspace/source/structure.d.ts +21 -0
  91. package/dist-lib/types/workspace/source/textSource.d.ts +28 -0
  92. package/dist-lib/types/workspace/tokens/TokenLibraryContext.d.ts +11 -0
  93. package/dist-lib/types/workspace/tokens/TokenLibraryWorkspace.d.ts +14 -0
  94. package/dist-lib/types/workspace/tokens/contracts.d.ts +74 -0
  95. package/dist-lib/types/workspace/tokens/controller.d.ts +44 -0
  96. package/dist-lib/types/workspace/view/PrototypePlayer.d.ts +17 -0
  97. package/dist-lib/types/workspace/view/StoryboardWorkspace.d.ts +3 -0
  98. package/dist-lib/types/workspace/view/prototypePlayback.d.ts +46 -0
  99. package/draft-preview.d.ts +54 -0
  100. package/inspect.d.ts +2 -0
  101. package/node/design-session.mjs +3 -0
  102. package/node/inspect-plugin.mjs +3 -1
  103. package/node/inspect-writeback.mjs +18 -2
  104. package/node/preview-artifact-store.mjs +10 -7
  105. package/node/source-archive.mjs +88 -0
  106. package/node/source-bindings.mjs +65 -0
  107. package/node/source-file-lock.mjs +15 -0
  108. package/node/source-file-plan.mjs +162 -0
  109. package/node/source-file-proofs.mjs +44 -0
  110. package/node/source-responsive-codec.d.mts +17 -0
  111. package/node/source-responsive-codec.mjs +133 -0
  112. package/node/source-responsive.mjs +189 -0
  113. package/node/source-structure-reconcile.mjs +186 -0
  114. package/node/source-structure-wrapper-codec.d.mts +20 -0
  115. package/node/source-structure-wrapper-codec.mjs +205 -0
  116. package/node/source-structure.mjs +404 -0
  117. package/node/token-source-references.mjs +136 -0
  118. package/node/workspace-draft-preview-plugin.mjs +70 -0
  119. package/node/workspace-draft-preview.mjs +231 -0
  120. package/node/workspace-source-identity.d.mts +1 -0
  121. package/node/workspace-source-identity.mjs +21 -0
  122. package/node/workspace-source-plan.mjs +195 -0
  123. package/package.json +52 -6
  124. package/source-files.d.ts +35 -0
  125. package/source-responsive.d.ts +10 -0
  126. package/source-structure.d.ts +155 -0
  127. package/workspace-source-plan.d.ts +44 -0
  128. package/docs/coverage-contracts.md +0 -444
  129. package/docs/screen-state-contract.md +0 -252
@@ -0,0 +1,37 @@
1
+ import type { BindingDiagnostic, BindingNodeContext, BindingRuntimeScope, BindingValueResult, DataBindingDocument, DataCatalog, DataField, DataFixtureContext, DataPreviewResolver } from './contracts.js';
2
+ export interface ProjectedDataBinding {
3
+ bindingId: string;
4
+ nodeId: string;
5
+ slotId: string;
6
+ rowPath: BindingRuntimeScope['rowPath'];
7
+ /** The source result remains distinct from any missing-value presentation. */
8
+ result: BindingValueResult;
9
+ presentation: {
10
+ kind: 'value';
11
+ value: unknown;
12
+ } | {
13
+ kind: 'hidden';
14
+ } | {
15
+ kind: 'empty';
16
+ } | {
17
+ kind: 'error';
18
+ message: string;
19
+ };
20
+ }
21
+ export interface ProjectedDataRow {
22
+ repeatId: string;
23
+ templateNodeId: string;
24
+ rowPath: BindingRuntimeScope['rowPath'];
25
+ }
26
+ export interface DataProjection {
27
+ values: readonly ProjectedDataBinding[];
28
+ rows: readonly ProjectedDataRow[];
29
+ diagnostics: readonly BindingDiagnostic[];
30
+ }
31
+ /** Executable values remain opaque; only the declared field boundary is validated. */
32
+ export declare function readDataField(field: DataField, scope: BindingRuntimeScope, resolver: DataPreviewResolver): BindingValueResult;
33
+ /** Preview is a projection: it never changes a document, its history, or source expressions. */
34
+ export declare function projectDataBindings(catalog: DataCatalog, document: DataBindingDocument, nodes: readonly BindingNodeContext[], fixture: DataFixtureContext, resolver: DataPreviewResolver, options?: {
35
+ maxRows?: number;
36
+ maxDepth?: number;
37
+ }): DataProjection;
@@ -0,0 +1,109 @@
1
+ import type { BindingDiagnostic, BindingNodeContext, BindingValidationResult, DataBinding, DataBindingDocument, DataCatalog, DataCatalogIdentity, DataField, RepeatBinding } from './contracts.js';
2
+ /** A small expression language issued by a host source adapter, never by sampled data. */
3
+ export type BindingSourceExpression = {
4
+ kind: 'identifier';
5
+ name: string;
6
+ } | {
7
+ kind: 'member';
8
+ object: BindingSourceExpression;
9
+ property: string;
10
+ optional?: boolean;
11
+ } | {
12
+ kind: 'call';
13
+ helper: string;
14
+ arguments: readonly BindingSourceExpression[];
15
+ } | {
16
+ kind: 'literal';
17
+ value: string | number | boolean | null;
18
+ } | {
19
+ kind: 'coalesce';
20
+ value: BindingSourceExpression;
21
+ fallback: BindingSourceExpression;
22
+ };
23
+ export interface BindingSourceProof {
24
+ file: string;
25
+ sourceRevision: string;
26
+ /** SHA-256 of the complete original UTF-8 source file. */
27
+ fileHash: string;
28
+ start: number;
29
+ end: number;
30
+ /** Original expression at this exact range. Not a fixture value. */
31
+ expected: string;
32
+ }
33
+ export interface BindingSourceResolution {
34
+ sourceRef: string;
35
+ expression: BindingSourceExpression;
36
+ proof: BindingSourceProof;
37
+ /** Identifiers proven to be in lexical scope by the host source adapter. */
38
+ identifiers: readonly string[];
39
+ /** Existing callable symbols explicitly approved by the host. No new hooks or imports are guessed. */
40
+ helpers: readonly string[];
41
+ /** A source adapter must explicitly acknowledge the presentation contract it emits. */
42
+ presentation: {
43
+ missing: DataBinding['missing'];
44
+ formatter?: DataBinding['formatter'];
45
+ };
46
+ }
47
+ export interface RepeatSourceResolution {
48
+ sourceRef: string;
49
+ expression: BindingSourceExpression;
50
+ proof: BindingSourceProof;
51
+ identifiers: readonly string[];
52
+ helpers: readonly string[];
53
+ itemIdentifier: string;
54
+ keyExpression: BindingSourceExpression;
55
+ }
56
+ export interface BindingSourceAdapter {
57
+ id: string;
58
+ version: string;
59
+ resolveBinding(context: {
60
+ catalog: DataCatalog;
61
+ document: DataBindingDocument;
62
+ binding: DataBinding;
63
+ field: DataField;
64
+ }): BindingSourceResolution | {
65
+ unavailable: string;
66
+ };
67
+ resolveRepeat?(context: {
68
+ catalog: DataCatalog;
69
+ document: DataBindingDocument;
70
+ repeat: RepeatBinding;
71
+ field: DataField;
72
+ }): RepeatSourceResolution | {
73
+ unavailable: string;
74
+ };
75
+ }
76
+ export interface BindingSourcePlan {
77
+ schema: 'pygmalion.binding-source-plan';
78
+ version: 1;
79
+ catalog: DataCatalogIdentity;
80
+ adapter: {
81
+ id: string;
82
+ version: string;
83
+ };
84
+ documentFingerprint: string;
85
+ bindings: readonly {
86
+ bindingId: string;
87
+ nodeId: string;
88
+ slotId: string;
89
+ resolution: BindingSourceResolution;
90
+ }[];
91
+ repeats: readonly {
92
+ repeatId: string;
93
+ templateNodeId: string;
94
+ resolution: RepeatSourceResolution;
95
+ }[];
96
+ }
97
+ export declare function bindingDocumentFingerprint(document: DataBindingDocument): string;
98
+ export declare function validateBindingSourceExpression(input: unknown, identifiers: readonly string[], helpers: readonly string[], options?: {
99
+ allowLiteralRoot?: boolean;
100
+ }): boolean;
101
+ export declare function printBindingSourceExpression(expression: BindingSourceExpression): string;
102
+ export declare function validBindingSourceProof(input: unknown, sourceRevision: string): input is BindingSourceProof;
103
+ export declare function validateBindingSourcePlan(input: unknown): BindingValidationResult;
104
+ /** Compile a reviewed-source proposal. This never mutates source and never emits literal-prop operations. */
105
+ export declare function compileBindingSourcePlan(catalog: DataCatalog, document: DataBindingDocument, nodes: readonly BindingNodeContext[], adapter?: BindingSourceAdapter): {
106
+ status: 'ready' | 'blocked';
107
+ diagnostics: readonly BindingDiagnostic[];
108
+ plan?: BindingSourcePlan;
109
+ };
@@ -0,0 +1,9 @@
1
+ import type { DocumentEngine } from '../document/contracts.js';
2
+ import type { DataFixtureContext, HostDataCapabilities } from './contracts.js';
3
+ /** Async fixture state stays outside the authoring document and command history. */
4
+ export declare function useDataProjection(engine: DocumentEngine, capabilities: HostDataCapabilities, screenId: string, fixtureId: string | undefined): {
5
+ projection: import("./preview.js").DataProjection | null;
6
+ fixture: DataFixtureContext | undefined;
7
+ error: string | undefined;
8
+ status: "unavailable" | "ready" | "loading" | "error";
9
+ };
@@ -0,0 +1,8 @@
1
+ import type { BindingDiagnostic, BindingNodeContext, BindingScopeUse, BindingValidationResult, DataBindingDocument, DataCatalog } from './contracts.js';
2
+ export declare function isBindingScopeUse(value: unknown): value is BindingScopeUse;
3
+ export declare function isDataBindingDocument(input: unknown): input is DataBindingDocument;
4
+ /** Resolve lexical scope from declarations, never from displayed values or object paths. */
5
+ export declare function bindingScopeId(catalog: DataCatalog, document: DataBindingDocument, use: BindingScopeUse): string | undefined;
6
+ export declare function validateDataBindings(catalog: DataCatalog, input: unknown, nodeList: readonly BindingNodeContext[]): BindingValidationResult;
7
+ /** Contribute only newly introduced errors; the document engine owns rollback and undo. */
8
+ export declare function preflightBindingReparent(catalog: DataCatalog, document: DataBindingDocument, beforeNodes: readonly BindingNodeContext[], afterNodes: readonly BindingNodeContext[]): readonly BindingDiagnostic[];
@@ -7,6 +7,8 @@ import { InspectSession } from '../editor/inspect.js';
7
7
  import { HostBindings, type HostBindingsInit } from './hostBindings.js';
8
8
  import { type EditorRuntimeDebug } from './debug.js';
9
9
  import type { EditorTransport } from '../contract/transport.js';
10
+ import { WorkspaceController } from '../workspace/controller.js';
11
+ import { WorkspaceDocumentSessions } from '../workspace/documentSessions.js';
10
12
  export interface EditorRuntimeOptions {
11
13
  /** Initial host values; every one can also be set later through `runtime.host`. */
12
14
  host?: HostBindingsInit;
@@ -18,6 +20,10 @@ export interface EditorRuntimeOptions {
18
20
  transport?: EditorTransport;
19
21
  }
20
22
  export interface EditorRuntime {
23
+ /** Independent navigation contexts for the three workspace modes. */
24
+ readonly workspace: WorkspaceController;
25
+ /** Canonical draft engines survive workspace navigation, scoped by source identity. */
26
+ readonly documents: WorkspaceDocumentSessions;
21
27
  readonly store: EditorStore;
22
28
  readonly host: HostBindings;
23
29
  readonly transport: EditorTransport;
@@ -0,0 +1,112 @@
1
+ import type { CSSProperties } from 'react';
2
+ import type { DesignDocument, DocumentDiagnostic, DocumentNode, DocumentNodeKind, DocumentValue } from './contracts.js';
3
+ export declare const BLEND_MODES: readonly ["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"];
4
+ export type BlendMode = typeof BLEND_MODES[number];
5
+ interface PaintCommon {
6
+ opacity?: number;
7
+ visible?: boolean;
8
+ blendMode?: BlendMode;
9
+ }
10
+ export interface SolidPaint extends PaintCommon {
11
+ type: 'solid';
12
+ color: string;
13
+ }
14
+ export interface GradientStop {
15
+ position: number;
16
+ color: string;
17
+ opacity?: number;
18
+ }
19
+ export interface GradientPaint extends PaintCommon {
20
+ type: 'linear' | 'radial' | 'angular';
21
+ stops: GradientStop[];
22
+ angle?: number;
23
+ center?: {
24
+ x: number;
25
+ y: number;
26
+ };
27
+ radius?: number;
28
+ }
29
+ export interface ImagePaint extends PaintCommon {
30
+ type: 'image';
31
+ assetId: string;
32
+ scaleMode: 'fill' | 'fit' | 'crop' | 'tile';
33
+ scale?: number;
34
+ }
35
+ export type Paint = SolidPaint | GradientPaint | ImagePaint;
36
+ export interface Stroke {
37
+ color: string;
38
+ weight: number;
39
+ align?: 'inside' | 'center' | 'outside';
40
+ dashes?: number[];
41
+ cap?: 'butt' | 'round' | 'square';
42
+ join?: 'miter' | 'round' | 'bevel';
43
+ sides?: {
44
+ top: number;
45
+ right: number;
46
+ bottom: number;
47
+ left: number;
48
+ };
49
+ opacity?: number;
50
+ visible?: boolean;
51
+ }
52
+ export interface ShadowEffect {
53
+ type: 'drop-shadow' | 'inner-shadow';
54
+ x: number;
55
+ y: number;
56
+ blur: number;
57
+ spread?: number;
58
+ color: string;
59
+ visible?: boolean;
60
+ }
61
+ export interface BlurEffect {
62
+ type: 'layer-blur' | 'background-blur';
63
+ radius: number;
64
+ visible?: boolean;
65
+ }
66
+ export type Effect = ShadowEffect | BlurEffect;
67
+ /** Paints and strokes use bottom-to-top order in this document format. */
68
+ export interface Appearance {
69
+ paints: Paint[];
70
+ strokes: Stroke[];
71
+ effects: Effect[];
72
+ opacity?: number;
73
+ blendMode?: BlendMode | 'pass-through';
74
+ }
75
+ export declare const APPEARANCE_KEYS: readonly ["paints", "strokes", "effects", "blendMode", "opacity"];
76
+ export declare const isAppearanceColor: (v: unknown) => v is string;
77
+ export declare function isPaint(v: unknown): v is Paint;
78
+ export declare function isStroke(v: unknown): v is Stroke;
79
+ export declare function isEffect(v: unknown): v is Effect;
80
+ export declare function normalizePaint(paint: Paint): Paint;
81
+ export declare function normalizeAppearance(value: Appearance): Appearance;
82
+ export declare function nodeAppearance(node: Pick<DocumentNode, 'kind' | 'properties'>): Appearance;
83
+ /** Replaces only appearance keys; one ordinary solid retains the legacy source mapping. */
84
+ export declare function appearanceProperties(properties: Record<string, DocumentValue>, appearance: Appearance, kind?: DocumentNodeKind): Record<string, DocumentValue>;
85
+ export declare function appearanceDiagnostics(node: DocumentNode): DocumentDiagnostic[];
86
+ export declare const colorWithOpacity: (color: string, opacity?: number) => string;
87
+ export declare function paintToCss(paint: Paint, document?: Pick<DesignDocument, 'metadata'>): CSSProperties;
88
+ export declare function strokeToCss(stroke: Stroke): CSSProperties;
89
+ /** Layer effects. Paints use separate surfaces so image opacity does not fade the node's children. */
90
+ export declare function appearanceToCss(node: DocumentNode, options?: {
91
+ document?: Pick<DesignDocument, 'metadata'>;
92
+ }): CSSProperties;
93
+ export declare const escapeSvg: (value: string | number) => string;
94
+ /** CSS gradient endpoints in pixel space, including non-square boxes. */
95
+ export declare function linearGradientLine(width: number, height: number, angle?: number): {
96
+ x1: number;
97
+ y1: number;
98
+ x2: number;
99
+ y2: number;
100
+ };
101
+ export interface SvgAppearance {
102
+ defs: string;
103
+ fills: Record<string, string | number>[];
104
+ strokes: Record<string, string | number>[];
105
+ diagnostics: DocumentDiagnostic[];
106
+ }
107
+ /** SVG presentation attributes and safe definitions. Angular gradients have no native SVG paint server. */
108
+ export declare function appearanceToSvg(node: DocumentNode, options?: {
109
+ document?: Pick<DesignDocument, 'metadata'>;
110
+ idPrefix?: string;
111
+ }): SvgAppearance;
112
+ export {};
@@ -0,0 +1,204 @@
1
+ import type { DesignDocument, DocumentDiagnostic, DocumentDuplicateMetadataRemapper, DocumentNode, DocumentTransaction, DocumentValue } from './contracts.js';
2
+ /**
3
+ * Asset store of a design document. Images and SVG sources live under
4
+ * `document.metadata.assets` as plain JSON so a saved document is
5
+ * self-contained; nodes reference them by id through an image paint
6
+ * (`{ type: 'image', assetId, scaleMode }` inside `properties.paints`) or,
7
+ * for editable SVG imports, through `properties.sourceAssetId` on the
8
+ * imported root.
9
+ *
10
+ * Ids are content-addressed (`asset:` + the first 24 hex digits of the
11
+ * SHA-256 of the bytes), so importing the same file twice stores it once and
12
+ * pasting between documents merges by id without renaming references. All
13
+ * functions here are pure and free of DOM access; hashing and dimension
14
+ * probing work on bytes.
15
+ */
16
+ export declare const ASSETS_METADATA_KEY = "assets";
17
+ export declare const ASSET_STORE_VERSION = 1;
18
+ export declare const IMAGE_MEDIA_TYPES: readonly ["image/png", "image/jpeg", "image/gif", "image/webp"];
19
+ export declare const IMAGE_SCALE_MODES: readonly ["fill", "fit", "crop", "tile"];
20
+ export declare const IMAGE_SCALE_MODE_LABELS: Readonly<Record<ImageScaleMode, string>>;
21
+ /** Placement default: an image larger than this is scaled down to fit when placed as a layer. */
22
+ export declare const IMAGE_PLACEMENT_MAX = 800;
23
+ export type ImageMediaType = (typeof IMAGE_MEDIA_TYPES)[number];
24
+ export type ImageScaleMode = (typeof IMAGE_SCALE_MODES)[number];
25
+ export type ImageAssetSource = {
26
+ type: 'data';
27
+ base64: string;
28
+ } | {
29
+ type: 'reference';
30
+ url: string;
31
+ };
32
+ export interface ImageAsset {
33
+ kind: 'image';
34
+ id: string;
35
+ name: string;
36
+ mediaType: ImageMediaType;
37
+ width: number;
38
+ height: number;
39
+ /** SHA-256 of the encoded bytes, lowercase hex. Reference sources carry the hash the host supplied. */
40
+ contentHash: string;
41
+ byteLength?: number;
42
+ source: ImageAssetSource;
43
+ }
44
+ export interface SvgAsset {
45
+ kind: 'svg';
46
+ id: string;
47
+ name: string;
48
+ markup: string;
49
+ width: number;
50
+ height: number;
51
+ contentHash: string;
52
+ }
53
+ export type DocumentAsset = ImageAsset | SvgAsset;
54
+ export interface AssetStore {
55
+ version: 1;
56
+ items: Record<string, DocumentAsset>;
57
+ }
58
+ export interface ImagePaint {
59
+ type: 'image';
60
+ assetId: string;
61
+ scaleMode: ImageScaleMode;
62
+ opacity?: number;
63
+ visible?: boolean;
64
+ blendMode?: string;
65
+ scale?: number;
66
+ }
67
+ export interface ImageAssetInput {
68
+ name: string;
69
+ /** Encoded bytes, a base64 string, or a `data:` URL. */
70
+ data?: Uint8Array | string;
71
+ /** A host-served location; requires `mediaType`, `width`, `height`, and `contentHash`. */
72
+ url?: string;
73
+ mediaType?: ImageMediaType;
74
+ width?: number;
75
+ height?: number;
76
+ contentHash?: string;
77
+ }
78
+ export interface SvgAssetInput {
79
+ name: string;
80
+ markup: string;
81
+ width?: number;
82
+ height?: number;
83
+ }
84
+ export interface AssetFileLike {
85
+ name: string;
86
+ type?: string;
87
+ arrayBuffer(): Promise<ArrayBuffer>;
88
+ }
89
+ export type InventoryAssetMedia = {
90
+ kind: 'svg';
91
+ markup: string;
92
+ } | {
93
+ kind: 'image';
94
+ mediaType?: ImageMediaType;
95
+ width?: number;
96
+ height?: number;
97
+ data?: string;
98
+ url?: string;
99
+ contentHash?: string;
100
+ };
101
+ export interface InventoryAssetEntry {
102
+ id: string;
103
+ name: string;
104
+ media?: InventoryAssetMedia;
105
+ }
106
+ /** SHA-256 of bytes as lowercase hex; synchronous so the document engine can stay synchronous. */
107
+ export declare function sha256Hex(bytes: Uint8Array): string;
108
+ export declare function bytesToBase64(bytes: Uint8Array): string;
109
+ /** Decodes standard or URL-safe base64, with or without padding; null on any other character. */
110
+ export declare function base64ToBytes(text: string): Uint8Array | null;
111
+ /** Media type from the byte signature; null for anything that is not PNG, JPEG, GIF, or WebP. */
112
+ export declare function sniffImageMediaType(bytes: Uint8Array): ImageMediaType | null;
113
+ /** Pixel dimensions from the header of a PNG, JPEG, GIF, or WebP; null when the header is incomplete. */
114
+ export declare function readImageDimensions(bytes: Uint8Array): {
115
+ width: number;
116
+ height: number;
117
+ mediaType: ImageMediaType;
118
+ } | null;
119
+ /** Width and height an SVG declares on its root: `width`/`height` in px, otherwise the `viewBox` size. */
120
+ export declare function svgIntrinsicSize(markup: string): {
121
+ width: number;
122
+ height: number;
123
+ } | null;
124
+ export declare const assetIdFor: (contentHash: string) => string;
125
+ export declare const safeAssetUrl: (url: string) => boolean;
126
+ export declare const safeSvgMarkup: (markup: string) => boolean;
127
+ export declare function isDocumentAsset(value: unknown): value is DocumentAsset;
128
+ export declare function isAssetStore(value: unknown): value is AssetStore;
129
+ export declare function isImagePaint(value: unknown): value is ImagePaint;
130
+ export declare const emptyAssetStore: () => AssetStore;
131
+ /** Detached asset store of a document; absent metadata is an empty store. Invalid metadata is reported by `assetStoreDiagnostics`. */
132
+ export declare function documentAssets(document: Pick<DesignDocument, 'metadata'>): AssetStore;
133
+ /** Verifies payload bytes independently of the structural asset schema. */
134
+ export declare function assetIntegrityProblem(asset: DocumentAsset): string | null;
135
+ export declare function assetStoreDiagnostics(document: Pick<DesignDocument, 'metadata'>): DocumentDiagnostic[];
136
+ /** Canonical JSON for `metadata.assets`: known keys in a stable order; undefined when the store is empty. */
137
+ export declare function serializeAssetStore(store: AssetStore): {
138
+ [key: string]: DocumentValue;
139
+ } | undefined;
140
+ /** The asset a node or paint refers to, or null. Provided for the appearance owner's image paints. */
141
+ export declare function resolveAsset(document: Pick<DesignDocument, 'metadata'>, assetId: string): DocumentAsset | null;
142
+ export declare function createImageAsset(input: ImageAssetInput): ImageAsset;
143
+ export declare function createSvgAsset(input: SvgAssetInput): SvgAsset;
144
+ /** Adds an asset; an identical asset (same id and hash) is a no-op that keeps the existing entry. */
145
+ export declare function addAsset(store: AssetStore, asset: DocumentAsset): AssetStore;
146
+ export declare function removeAsset(store: AssetStore, assetId: string): AssetStore;
147
+ export declare function renameAsset(store: AssetStore, assetId: string, name: string): AssetStore;
148
+ /** Merges every asset of `source` into `target`; a same-id entry with different content is refused. */
149
+ export declare function mergeAssetStores(target: AssetStore, source: AssetStore): AssetStore;
150
+ /** Writes the store to `metadata.assets`; an empty store removes the key so plain documents keep empty metadata. */
151
+ export declare function writeDocumentAssets(transaction: Pick<DocumentTransaction, 'setMetadata'>, store: AssetStore): void;
152
+ export declare function addDocumentAsset(transaction: Pick<DocumentTransaction, 'setMetadata'>, document: Pick<DesignDocument, 'metadata'>, asset: DocumentAsset): void;
153
+ /** Every image paint of a node's own properties, in paint order. */
154
+ export declare function nodeImagePaints(node: Pick<DocumentNode, 'properties'>): ImagePaint[];
155
+ /** Asset ids a node refers to directly: image paints (own and override properties) and an SVG import source. */
156
+ export declare function nodeAssetIds(node: DocumentNode): string[];
157
+ /** Nodes per referenced asset id, including ids that are missing from the store. */
158
+ export declare function assetReferences(document: Pick<DesignDocument, 'nodes'>): Record<string, string[]>;
159
+ export declare function unusedAssetIds(document: Pick<DesignDocument, 'nodes' | 'metadata'>): string[];
160
+ export declare function pruneUnusedAssets(document: Pick<DesignDocument, 'nodes' | 'metadata'>): AssetStore;
161
+ /** Referenced asset ids that the store does not contain. */
162
+ export declare function missingAssetIds(document: Pick<DesignDocument, 'nodes' | 'metadata'>): string[];
163
+ /** Duplicating layers shares assets (ids are content-addressed), so the sidecar passes through unchanged. */
164
+ export declare const assetsDuplicateMetadata: DocumentDuplicateMetadataRemapper;
165
+ /** A URL usable by `<img src>` or `background-image`: a data URL for stored bytes, the location for references. */
166
+ export declare function assetSourceUrl(asset: DocumentAsset): string;
167
+ export declare const imagePaint: (assetId: string, scaleMode?: ImageScaleMode) => ImagePaint;
168
+ /**
169
+ * CSS for one image paint as a background, keyed like React `CSSProperties`. `fill` covers the box,
170
+ * `fit` letterboxes, `crop` covers (the crop transform is not modelled), `tile` repeats at natural size.
171
+ * A missing asset yields an empty object so the layer keeps its other paints.
172
+ */
173
+ export declare function imagePaintCss(source: Pick<DesignDocument, 'metadata'> | AssetStore, paint: ImagePaint): Record<string, string>;
174
+ /** Background CSS of a node's first image paint; the appearance owner layers this under its own projection. */
175
+ export declare function nodeImageCss(document: Pick<DesignDocument, 'metadata'>, node: Pick<DocumentNode, 'properties'>): Record<string, string>;
176
+ /** Size for a newly placed image: natural size, scaled down uniformly to fit the limit. */
177
+ export declare function imagePlacementSize(asset: Pick<DocumentAsset, 'width' | 'height'>, limit?: number): {
178
+ width: number;
179
+ height: number;
180
+ };
181
+ /** A frame whose only paint is the image; this is the "image layer" of the editor. */
182
+ export declare function imageNode(input: {
183
+ id: string;
184
+ asset: DocumentAsset;
185
+ name?: string;
186
+ scaleMode?: ImageScaleMode;
187
+ x?: number;
188
+ y?: number;
189
+ limit?: number;
190
+ }): DocumentNode;
191
+ export declare function isImageNode(node: DocumentNode): boolean;
192
+ /** Reads dropped or chosen files into assets; failures become diagnostics that name the file. */
193
+ export declare function importAssetFiles(files: Iterable<AssetFileLike>): Promise<{
194
+ assets: DocumentAsset[];
195
+ diagnostics: DocumentDiagnostic[];
196
+ }>;
197
+ /** Builds a store from a host inventory whose entries carry media; entries without media are skipped. */
198
+ export declare function assetsFromInventory(entries: Iterable<InventoryAssetEntry>): {
199
+ store: AssetStore;
200
+ assetIds: Record<string, string>;
201
+ diagnostics: DocumentDiagnostic[];
202
+ };
203
+ /** Custom source compilers must acknowledge asset and export sidecars rather than silently dropping them. */
204
+ export declare function assetInteropSourceDeltaDiagnostics(before: DesignDocument, after: DesignDocument): DocumentDiagnostic[];