@dojo-video-engine/layout 0.0.0-stage → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dojo Video Engine contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,110 @@
1
- # Temporary Holding Version
1
+ # @dojo-video-engine/layout
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `@dojo-video-engine/layout` is Dojo Video Engine's bounded semantic authoring layer for
4
+ stacks, wrapping rows/columns, grids, overlays, intrinsic sizing, safe areas,
5
+ and small sibling-relative constraints. It compiles a flat plan over existing
6
+ child IDs into ordinary numeric Scene v1 geometry.
7
+
8
+ It is not a second render format. Plans are transient authoring input; the
9
+ compiler returns a valid Scene v1 and the renderer, player, export worker, and
10
+ stored project continue to consume only that Scene.
11
+
12
+ The compiled Scene is a target-size-specific render projection, not responsive
13
+ authoring source. An editor that needs to reflow later must retain the original
14
+ source Scene plus its LayoutPlan(s) and recompile those for the new target.
15
+ Never keep only the compiled projection as the sole editable source: its
16
+ semantic `hug`/`fill`/track/constraint intent has deliberately compiled away.
17
+
18
+ ```ts
19
+ import { compileLayout, item, row } from "@dojo-video-engine/layout";
20
+
21
+ const plan = row({
22
+ items: [
23
+ item("portrait", { width: "fill", aspectRatio: 1 }),
24
+ item("copy", { width: "fill" }),
25
+ ],
26
+ gap: "4%",
27
+ padding: { x: "6%", y: "5%" },
28
+ align: "center",
29
+ });
30
+
31
+ const result = compileLayout(scene, plan, {
32
+ textMetrics,
33
+ mediaMetrics,
34
+ missingMediaMetrics: { mode: "error" },
35
+ fontFallbackPolicy: "allow-system", // deterministic projects use a font asset
36
+ });
37
+ ```
38
+
39
+ ## Contract
40
+
41
+ The public tool shape is deliberately flat and non-recursive:
42
+
43
+ - `containerId` is `$root` or one existing Scene node;
44
+ - every `items[].id` names one direct visual child;
45
+ - item order controls flow and grid auto-placement without reordering Scene
46
+ paint order;
47
+ - `layout.kind` is `stack`, `grid`, or `overlay`;
48
+ - `row()` and `column()` are typed sugar for `stack` axes;
49
+ - sizes are fixed pixels, percentages, `hug`, or `fill`;
50
+ - grow/shrink, min/max, aspect ratio, margins, gaps, wrapping, distribution,
51
+ grid spans, overlay anchors, and bounded sibling constraints are explicit;
52
+ - safe-area and padding insets are resolved against the target container;
53
+ - output children have numeric `position`, `left`, `top`, `width`, and
54
+ `height` and no stale Scene-v1 geometry fields.
55
+
56
+ `layoutPlanSchema` and `validateLayoutPlan()` own the complete runtime contract.
57
+ `layoutPlanJsonSchema()` exposes its generated draft-07 structural shape and
58
+ adds kind-specific conditions, so tool validators reject fields a layout kind
59
+ cannot consume. Draft-07 cannot express uniqueness by an object's `id` value;
60
+ every tool host must still call `validateLayoutPlan()` before compilation.
61
+ `tryCompileLayout()` returns portable structured failures; `compileLayout()`
62
+ throws `LayoutCompileError`.
63
+
64
+ ## Intrinsic metrics
65
+
66
+ The compiler uses core's prepared, synchronous `TextMetricsProvider` and
67
+ `MediaMetricsProvider`. Every measurement reports field-level `exact`,
68
+ `declared`, or `estimated` provenance. Media with missing intrinsic dimensions
69
+ never receives a hidden default: choose `mode: "error"` or provide explicit
70
+ type-specific fallback sizes.
71
+
72
+ Text planning defaults to `fontFallbackPolicy: "require-prepared"`. Family
73
+ lists are parsed in author order and the first family matching a declared font
74
+ asset is compiled to that exact asset id; the id itself must be representable
75
+ as one unambiguous Scene font family (spaces are safe, comma/quote escapes are
76
+ not). A prepared text-metrics provider is also required. `"allow-system"` is an
77
+ explicit portability escape hatch and always emits estimated font evidence
78
+ plus a warning.
79
+
80
+ Layout v2 text resolves an omitted direction through its bundled deterministic
81
+ first-strong scan; explicit `ltr`/`rtl` wins and host-dependent `inherit` is
82
+ rejected. Rich runs are rejected for intrinsic fitting by default; the
83
+ legacy-unsafe opt-in is intentionally visible. Fixed boxes can still carry
84
+ legacy rich text because no v2 shaping decision is made.
85
+ Successful item measurements retain the detached text plan—source cluster
86
+ ranges, planned lines/ellipsis, fit status, direction, and provenance—so an
87
+ editor or agent can explain the compiled Scene-v1 text.
88
+
89
+ The bundled cluster segmenter covers combining marks, emoji modifiers/ZWJ,
90
+ regional-indicator flags, and CRLF without depending on host Unicode data. It
91
+ is deliberately not a complete UAX #29 implementation for modern Indic
92
+ conjunct chains without explicit ZWJ or decomposed Hangul Jamo; prefer
93
+ precomposed/shaped input for those cases.
94
+
95
+ ## Determinism and limits
96
+
97
+ Grid auto-placement is stable and non-dense; declared cells reserve their spans
98
+ before auto placement. Implicit row tracks fill the bounded grid, while column
99
+ auto-flow requires explicit rows so guard budgets never affect geometry. Grid
100
+ stretch applies only to `fill` or omitted/auto item sizes, never explicit fixed
101
+ sizes. Sibling constraints form a
102
+ bounded dependency DAG; unknown targets, cycles, multiple writers, collisions,
103
+ and out-of-bounds constrained results are errors. Plans, tracks, constraints,
104
+ text, solver steps, and coordinates all have host-tightenable budgets.
105
+
106
+ Semantic layout is a target-size snapshot. Recompile the same source Scene and
107
+ plan for portrait, square, or landscape output. Keep that source/plan pair for
108
+ future edits; the projection alone cannot recover semantic intent. Animating compiler-owned
109
+ geometry is rejected: retaining and reevaluating semantic layout per frame
110
+ would require a future Scene version and is outside this Scene v1 compiler.
@@ -0,0 +1,27 @@
1
+ export * from "./schema.js";
2
+ export * from "./types.js";
3
+ export * from "./text.js";
4
+ export { compileLayout, tryCompileLayout } from "./solver.js";
5
+ import { type GridLayout, type LayoutItem, type LayoutPlan, type OverlayLayout, type StackLayout } from "./schema.js";
6
+ export type LayoutItemOptions = Omit<LayoutItem, "id">;
7
+ /** Detached ergonomic item descriptor for TypeScript authoring. */
8
+ export declare function item(id: string, options?: LayoutItemOptions): LayoutItem;
9
+ type StackPlanOptions = Omit<StackLayout, "kind" | "axis"> & {
10
+ containerId?: string;
11
+ items: LayoutItem[];
12
+ };
13
+ /** Canonical one-dimensional layout constructor. */
14
+ export declare function stack(axis: "row" | "column", options: StackPlanOptions): LayoutPlan;
15
+ export declare function row(options: StackPlanOptions): LayoutPlan;
16
+ export declare function column(options: StackPlanOptions): LayoutPlan;
17
+ type GridPlanOptions = Omit<GridLayout, "kind"> & {
18
+ containerId?: string;
19
+ items: LayoutItem[];
20
+ };
21
+ export declare function grid(options: GridPlanOptions): LayoutPlan;
22
+ type OverlayPlanOptions = Omit<OverlayLayout, "kind"> & {
23
+ containerId?: string;
24
+ items: LayoutItem[];
25
+ };
26
+ export declare function overlay(options: OverlayPlanOptions): LayoutPlan;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAEvD,mEAAmE;AACnE,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAE5E;AAED,KAAK,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,oDAAoD;AACpD,wBAAgB,KAAK,CACnB,IAAI,EAAE,KAAK,GAAG,QAAQ,EACtB,OAAO,EAAE,gBAAgB,GACxB,UAAU,CAMZ;AAED,wBAAgB,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAEzD;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAE5D;AAED,KAAK,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,wBAAgB,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,UAAU,CAKzD;AAED,KAAK,kBAAkB,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,UAAU,CAK/D"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ export * from "./schema.js";
2
+ export * from "./types.js";
3
+ export * from "./text.js";
4
+ export { compileLayout, tryCompileLayout } from "./solver.js";
5
+ import { LAYOUT_CONTRACT_VERSION, LAYOUT_ROOT, layoutPlanSchema, } from "./schema.js";
6
+ /** Detached ergonomic item descriptor for TypeScript authoring. */
7
+ export function item(id, options = {}) {
8
+ return structuredClone({ id, ...options });
9
+ }
10
+ /** Canonical one-dimensional layout constructor. */
11
+ export function stack(axis, options) {
12
+ return makePlan(options.containerId, options.items, {
13
+ ...withoutPlanFields(options),
14
+ kind: "stack",
15
+ axis,
16
+ });
17
+ }
18
+ export function row(options) {
19
+ return stack("row", options);
20
+ }
21
+ export function column(options) {
22
+ return stack("column", options);
23
+ }
24
+ export function grid(options) {
25
+ return makePlan(options.containerId, options.items, {
26
+ ...withoutPlanFields(options),
27
+ kind: "grid",
28
+ });
29
+ }
30
+ export function overlay(options) {
31
+ return makePlan(options.containerId, options.items, {
32
+ ...withoutPlanFields(options),
33
+ kind: "overlay",
34
+ });
35
+ }
36
+ function makePlan(containerId, items, layout) {
37
+ return layoutPlanSchema.parse({
38
+ layoutVersion: LAYOUT_CONTRACT_VERSION,
39
+ containerId: containerId ?? LAYOUT_ROOT,
40
+ layout,
41
+ items,
42
+ });
43
+ }
44
+ function withoutPlanFields(value) {
45
+ const { containerId: _containerId, items: _items, ...rest } = value;
46
+ return rest;
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,gBAAgB,GAMjB,MAAM,aAAa,CAAC;AAIrB,mEAAmE;AACnE,MAAM,UAAU,IAAI,CAAC,EAAU,EAAE,UAA6B,EAAE;IAC9D,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC;AAOD,oDAAoD;AACpD,MAAM,UAAU,KAAK,CACnB,IAAsB,EACtB,OAAyB;IAEzB,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE;QAClD,GAAG,iBAAiB,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,OAAO;QACb,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,OAAyB;IAC3C,OAAO,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAyB;IAC9C,OAAO,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAOD,MAAM,UAAU,IAAI,CAAC,OAAwB;IAC3C,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE;QAClD,GAAG,iBAAiB,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,OAAO,CAAC,OAA2B;IACjD,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE;QAClD,GAAG,iBAAiB,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CACf,WAA+B,EAC/B,KAAmB,EACnB,MAA4B;IAE5B,OAAO,gBAAgB,CAAC,KAAK,CAAC;QAC5B,aAAa,EAAE,uBAAuB;QACtC,WAAW,EAAE,WAAW,IAAI,WAAW;QACvC,MAAM;QACN,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAExB,KAAQ;IACR,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}