machinalayout 0.1.0 → 0.2.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 (45) hide show
  1. package/README.md +280 -49
  2. package/dist/chunk-BJOQRPPX.js +382 -0
  3. package/dist/chunk-HU6XYOH7.js +133 -0
  4. package/dist/chunk-KYWOCAHK.js +205 -0
  5. package/dist/chunk-RJYRJ3LD.js +0 -0
  6. package/dist/chunk-TR24ERZT.js +66 -0
  7. package/dist/dispatch/index.d.ts +49 -0
  8. package/dist/dispatch/index.js +217 -0
  9. package/dist/index.d.ts +15 -238
  10. package/dist/index.js +596 -591
  11. package/dist/react/index.d.ts +33 -0
  12. package/dist/react/index.js +7 -0
  13. package/dist/react-native/index.d.ts +30 -0
  14. package/dist/react-native/index.js +83 -0
  15. package/dist/text/index.d.ts +10 -0
  16. package/dist/text/index.js +9 -0
  17. package/dist/text/react/index.d.ts +14 -0
  18. package/dist/text/react/index.js +7 -0
  19. package/dist/text/react-native/index.d.ts +16 -0
  20. package/dist/text/react-native/index.js +155 -0
  21. package/dist/text/vue/index.d.ts +113 -0
  22. package/dist/text/vue/index.js +202 -0
  23. package/dist/types-BudfpzZX.d.ts +184 -0
  24. package/dist/types-C4poVJpR.d.ts +74 -0
  25. package/dist/vue/index.d.ts +173 -0
  26. package/dist/vue/index.js +111 -0
  27. package/docs/adapter-packaging-a0-plan.md +352 -0
  28. package/docs/adapters.md +19 -0
  29. package/docs/api-coherence-m8-audit.md +397 -0
  30. package/docs/error-codes.md +84 -0
  31. package/docs/grid-arrange-m5a-contract.md +480 -0
  32. package/docs/grid-arrange.md +51 -0
  33. package/docs/layout-interpolation.md +52 -0
  34. package/docs/machina-dispatch-d0-contract.md +496 -0
  35. package/docs/machina-dispatch.md +143 -0
  36. package/docs/named-layers.md +40 -0
  37. package/docs/react-adapter.md +51 -69
  38. package/docs/react-native-adapter.md +56 -0
  39. package/docs/react-native-text-renderer.md +50 -0
  40. package/docs/reference-alignment-m7a-contract.md +384 -0
  41. package/docs/reference-alignment.md +44 -0
  42. package/docs/responsive-variants.md +54 -0
  43. package/docs/vue-adapter.md +55 -0
  44. package/docs/vue-text-renderer.md +55 -0
  45. package/package.json +60 -5
@@ -0,0 +1,111 @@
1
+ import {
2
+ toResolvedTree
3
+ } from "../chunk-TR24ERZT.js";
4
+
5
+ // src/vue/MachinaVueView.ts
6
+ import { computed, defineComponent, h } from "vue";
7
+ var normalizeLayerZ = (v) => v === void 0 || !Number.isFinite(v) || !Number.isInteger(v) || v < -5 || v > 5 ? 0 : v;
8
+ var getEffectiveLayer = (n, d) => n.layer ?? d;
9
+ var getEffectiveLayerZ = (n, l, d) => normalizeLayerZ(l[getEffectiveLayer(n, d)]?.z);
10
+ var MachinaVueView = defineComponent({
11
+ name: "MachinaVueView",
12
+ props: {
13
+ layout: { type: Object, required: true },
14
+ views: { type: Object, default: () => ({}) },
15
+ viewData: { type: Object, default: () => ({}) },
16
+ nodeData: { type: Object, default: () => ({}) },
17
+ layers: {
18
+ type: Object,
19
+ default: () => ({ base: { z: 0 } })
20
+ },
21
+ defaultLayer: { type: String, default: "base" },
22
+ debug: { type: Boolean, default: false },
23
+ rootClass: { type: null, default: void 0 },
24
+ rootStyle: { type: null, default: void 0 },
25
+ nodeClass: { type: null, default: void 0 },
26
+ nodeStyle: { type: null, default: void 0 },
27
+ nodeContainment: {
28
+ type: String,
29
+ default: "layout-paint"
30
+ },
31
+ nodeContentVisibility: { type: String, default: "none" },
32
+ nodeContainIntrinsicSize: { type: String, default: void 0 }
33
+ },
34
+ setup(props) {
35
+ const tree = computed(() => toResolvedTree(props.layout));
36
+ const renderNode = (node, parentRect) => {
37
+ const viewKey = node.view ?? node.slot;
38
+ const View = viewKey ? props.views[viewKey] : void 0;
39
+ const left = node.rect.x - parentRect.x;
40
+ const top = node.rect.y - parentRect.y;
41
+ const layer = getEffectiveLayer(node, props.defaultLayer);
42
+ const layerZ = getEffectiveLayerZ(node, props.layers, props.defaultLayer);
43
+ const baseStyle = {
44
+ position: "absolute",
45
+ left: `${left}px`,
46
+ top: `${top}px`,
47
+ width: `${node.rect.width}px`,
48
+ height: `${node.rect.height}px`,
49
+ boxSizing: "border-box",
50
+ zIndex: `${layerZ * 100 + (node.z ?? 0)}`,
51
+ ...props.nodeContainment === "layout-paint" ? { contain: "layout paint" } : null,
52
+ ...props.nodeContainment === "strict" ? { contain: "strict" } : null,
53
+ ...props.nodeContentVisibility === "auto" ? { contentVisibility: "auto" } : null,
54
+ ...props.nodeContainIntrinsicSize !== void 0 ? { containIntrinsicSize: props.nodeContainIntrinsicSize } : null,
55
+ ...props.debug ? { outline: "1px dashed rgba(59, 130, 246, 0.9)" } : null
56
+ };
57
+ const rendered = View && props.layout.nodes[node.id] ? h(View, {
58
+ id: node.id,
59
+ rect: { ...node.rect },
60
+ debugLabel: node.debugLabel,
61
+ node: {
62
+ ...props.layout.nodes[node.id],
63
+ rect: { ...props.layout.nodes[node.id].rect }
64
+ },
65
+ viewKey,
66
+ viewData: viewKey ? props.viewData[viewKey] : void 0,
67
+ nodeData: props.nodeData[node.id]
68
+ }) : null;
69
+ const kids = [...node.children].map((child, index) => ({ child, index })).sort(
70
+ (a, b) => getEffectiveLayerZ(a.child, props.layers, props.defaultLayer) - getEffectiveLayerZ(b.child, props.layers, props.defaultLayer) || (a.child.z ?? 0) - (b.child.z ?? 0) || a.index - b.index
71
+ ).map(({ child }) => renderNode(child, node.rect));
72
+ return h(
73
+ "div",
74
+ {
75
+ key: node.id,
76
+ class: props.nodeClass,
77
+ style: [baseStyle, props.nodeStyle],
78
+ "data-machina-node-id": node.id,
79
+ "data-machina-slot": node.slot,
80
+ "data-machina-view": viewKey,
81
+ "data-machina-debug-label": node.debugLabel,
82
+ "data-machina-layer": layer
83
+ },
84
+ [props.debug ? h("small", {}, node.debugLabel ?? node.id) : null, rendered, ...kids]
85
+ );
86
+ };
87
+ return () => {
88
+ const root = tree.value;
89
+ return h(
90
+ "div",
91
+ {
92
+ class: props.rootClass,
93
+ style: [
94
+ {
95
+ position: "relative",
96
+ width: `${root.rect.width}px`,
97
+ height: `${root.rect.height}px`,
98
+ boxSizing: "border-box"
99
+ },
100
+ props.rootStyle
101
+ ],
102
+ "data-machina-root-id": root.id
103
+ },
104
+ [renderNode(root, root.rect)]
105
+ );
106
+ };
107
+ }
108
+ });
109
+ export {
110
+ MachinaVueView
111
+ };
@@ -0,0 +1,352 @@
1
+ # Adapter Packaging A0 Plan
2
+
3
+ ## 1) Executive summary
4
+
5
+ MachinaLayout should stay as a **single npm package during `0.x`**, but move toward a **subpath-exported adapter model** so new adapters do not impose framework installs on every user.
6
+
7
+ Recommended direction:
8
+
9
+ - Keep `machinalayout` root import stable for compatibility during `0.x`.
10
+ - Add framework-specific adapter entrypoints as subpaths (`machinalayout/react`, `machinalayout/text/react`, future `machinalayout/react-native`, `machinalayout/vue`, etc.).
11
+ - Treat new framework peers (`react-native`, `vue`) as **optional peers** when their adapters are added.
12
+ - Keep runtime/package behavior unchanged in A0; implement packaging/build updates as A1 prerequisites.
13
+
14
+ ## 2) Current package/export state (observed)
15
+
16
+ ### Package/build
17
+
18
+ - Package name is `machinalayout`, version `0.1.0`, ESM package type.
19
+ - Build command uses `tsup` with a **single entry**: `src/index.ts`.
20
+ - Current output is a **single dist entrypoint**:
21
+ - `dist/index.js`
22
+ - `dist/index.d.ts`
23
+ - `exports` currently expose only `"."`.
24
+
25
+ ### Peer dependencies
26
+
27
+ - Current peers are:
28
+ - `react` (`>=18 <20`)
29
+ - `react-dom` (`>=18 <20`)
30
+ - No optional peer metadata yet.
31
+
32
+ ### Public exports and source layout
33
+
34
+ - `src/index.ts` re-exports core, React adapter (`./react`), and text module (`./text`).
35
+ - React adapter exists under `src/react`.
36
+ - Text parser/types and React text renderer exist under `src/text` and `src/text/react`.
37
+ - README examples/documentation currently import React adapter from root (`machinalayout`).
38
+
39
+ ### Packaging snapshot
40
+
41
+ - `npm pack --dry-run` currently includes `dist` (single bundle), README, LICENSE, and docs.
42
+ - No subpath build artifacts are currently emitted.
43
+
44
+ ## 3) Recommended package strategy
45
+
46
+ ### Evaluated options
47
+
48
+ #### A. Single package + subpath exports (recommended for now)
49
+
50
+ Pros:
51
+
52
+ - Minimal project/process overhead while API is still evolving.
53
+ - Keeps install/discovery simple for early adopters.
54
+ - Preserves existing import compatibility.
55
+
56
+ Cons:
57
+
58
+ - `exports`/build matrix becomes more complex.
59
+ - Peer policy must clearly separate required vs optional framework peers.
60
+
61
+ #### B. Separate packages (`@machina/*`) later
62
+
63
+ Pros:
64
+
65
+ - Clean dependency isolation per framework.
66
+ - Natural long-term scaling for adapters.
67
+
68
+ Cons:
69
+
70
+ - Multi-package release/publishing overhead now.
71
+ - More migration friction before APIs settle.
72
+
73
+ ### Decision
74
+
75
+ For `0.x`, use **single package + subpath exports**. Reassess split packages after adapter APIs stabilize and usage justifies monorepo/package split effort.
76
+
77
+ ## 4) Proposed subpath export map
78
+
79
+ Target import shapes:
80
+
81
+ ```ts
82
+ import { resolveLayoutRows } from "machinalayout";
83
+ import { MachinaReactView } from "machinalayout/react";
84
+ import { parseMachinaText } from "machinalayout/text";
85
+ import { MachinaTextView } from "machinalayout/text/react";
86
+ import { MachinaReactNativeView } from "machinalayout/react-native";
87
+ import { MachinaVueView } from "machinalayout/vue";
88
+ ```
89
+
90
+ Export policy:
91
+
92
+ - **Keep root exports unchanged during `0.x`** for compatibility.
93
+ - Introduce and document subpath exports as preferred for adapters.
94
+ - New adapters (`react-native`, `vue`, future) should be **subpath-only**.
95
+ - Existing root React exports remain temporarily for non-breaking transition.
96
+
97
+ ## 5) Peer dependency policy
98
+
99
+ ### Near term (`0.x`, current compatibility)
100
+
101
+ - Keep `react` and `react-dom` as non-optional peers while root still exports React adapter surfaces.
102
+ - When adding adapter subpaths:
103
+ - Add `react-native` peer + `peerDependenciesMeta.react-native.optional = true`.
104
+ - Add `vue` peer + `peerDependenciesMeta.vue.optional = true`.
105
+
106
+ ### Later (future major or de-rooting)
107
+
108
+ - If React DOM adapter is no longer root-exported, convert renderer peers to optional and strictly subpath-scoped usage.
109
+
110
+ Rationale: users should only need the framework peer for the adapter they import.
111
+
112
+ ## 6) Build output proposal
113
+
114
+ A1 prerequisite: move from single-entry build to multi-entry/subpath build.
115
+
116
+ Proposed dist shape:
117
+
118
+ ```txt
119
+ dist/index.js
120
+ dist/index.d.ts
121
+ dist/react/index.js
122
+ dist/react/index.d.ts
123
+ dist/text/index.js
124
+ dist/text/index.d.ts
125
+ dist/text/react/index.js
126
+ dist/text/react/index.d.ts
127
+ dist/react-native/index.js
128
+ dist/react-native/index.d.ts
129
+ dist/vue/index.js
130
+ dist/vue/index.d.ts
131
+ ```
132
+
133
+ Build notes:
134
+
135
+ - Use tsup multi-entry configuration (or equivalent) with explicit entry files.
136
+ - Externalize framework runtimes in adapter bundles:
137
+ - `react`, `react-dom`, `react/jsx-runtime`
138
+ - `react-native`
139
+ - `vue`
140
+ - Keep core runtime free of adapter-specific runtime imports.
141
+
142
+ ## 7) Source tree proposal
143
+
144
+ Recommended organization:
145
+
146
+ ```txt
147
+ src/
148
+ index.ts
149
+ react/
150
+ index.ts
151
+ MachinaReactView.tsx
152
+ react-native/
153
+ index.ts
154
+ MachinaReactNativeView.tsx
155
+ vue/
156
+ index.ts
157
+ MachinaVueView.ts
158
+ text/
159
+ index.ts
160
+ types.ts
161
+ parseMachinaText.ts
162
+ react/
163
+ index.ts
164
+ MachinaTextView.tsx
165
+ react-native/
166
+ index.ts
167
+ MachinaNativeTextView.tsx
168
+ vue/
169
+ index.ts
170
+ MachinaVueTextView.ts
171
+ ```
172
+
173
+ Guideline:
174
+
175
+ - Layout adapters: `src/<adapter>`.
176
+ - Text renderers: `src/text/<adapter>`.
177
+
178
+ This keeps parser/core text independent from renderer frameworks.
179
+
180
+ ## 8) Adapter API previews (non-binding)
181
+
182
+ ### React Native layout adapter
183
+
184
+ ```ts
185
+ export type { MachinaReactNativeViewProps, MachinaNativeSlotProps };
186
+ export { MachinaReactNativeView };
187
+ ```
188
+
189
+ Expected behavior:
190
+
191
+ - Uses RN `View` + style objects.
192
+ - No `className`, no DOM data-attributes.
193
+ - No DOM containment/content-visibility policy.
194
+ - Preserve layout semantics, `viewData`/`nodeData`, layers/z ordering, and parent-local coordinates.
195
+
196
+ ### Vue layout adapter
197
+
198
+ ```ts
199
+ export type { MachinaVueViewProps, MachinaVueSlotProps };
200
+ export { MachinaVueView };
201
+ ```
202
+
203
+ Expected behavior:
204
+
205
+ - Vue component/composable renderer using `h()`.
206
+ - Supports `layout`, `views`, `viewData`, `nodeData`, `layers`, `defaultLayer`, `debug`.
207
+ - Dynamic view mapping via component references.
208
+
209
+ ### Text
210
+
211
+ - `parseMachinaText` remains framework-agnostic in `machinalayout/text`.
212
+ - Framework renderers exposed by subpath (`text/react`, future `text/react-native`, `text/vue`).
213
+
214
+ ## 9) Test strategy
215
+
216
+ Principles:
217
+
218
+ - Core tests always run and remain framework-independent.
219
+ - Adapter tests are isolated by adapter folders and entrypoints.
220
+ - Avoid forcing heavy framework stacks for users who do not use them.
221
+
222
+ Proposed test layout:
223
+
224
+ ```txt
225
+ test/
226
+ core/...
227
+ react/...
228
+ react-native/...
229
+ vue/...
230
+ text/
231
+ core/...
232
+ react/...
233
+ react-native/...
234
+ vue/...
235
+ ```
236
+
237
+ Execution approach (A1+):
238
+
239
+ - Default CI lane: core + existing React lanes.
240
+ - Adapter lanes:
241
+ - RN adapter tests in dedicated job/environment.
242
+ - Vue adapter tests in dedicated job/environment.
243
+ - Early RN adapter tests can start with type-level/shape tests and minimal render checks before deeper platform-specific behavior.
244
+
245
+ ## 10) Documentation plan
246
+
247
+ Planned docs additions:
248
+
249
+ - `docs/react-native-adapter.md`
250
+ - `docs/vue-adapter.md`
251
+ - `docs/adapter-packaging-a0-plan.md` (this file)
252
+ - README update to clarify preferred import paths and adapter dependency expectations.
253
+
254
+ Docs guidance:
255
+
256
+ - Show subpath imports for framework adapters.
257
+ - Keep compatibility notes for root React imports during `0.x`.
258
+ - Explicitly state optional peer policy for non-default adapters.
259
+ - Keep adapter docs aligned to one conceptual model: Machina records author geometry, adapters render resolved rectangles in host primitives.
260
+ - Reinforce stable component registries (`views`) plus dynamic `viewData`/`nodeData` channels across React, React Native, and Vue.
261
+
262
+ ## 11) Migration / compatibility notes
263
+
264
+ - Do **not** break current root import patterns in immediate work.
265
+ - Maintain:
266
+
267
+ ```ts
268
+ import { MachinaReactView } from "machinalayout";
269
+ ```
270
+
271
+ through `0.x`.
272
+
273
+ - Mark subpath imports as preferred forward path.
274
+ - Consider root de-exports only in future major/split-package decision.
275
+
276
+ ## 12) Milestone decomposition
277
+
278
+ ### A1 — React Native layout adapter
279
+
280
+ Scope:
281
+
282
+ - Add `src/react-native` adapter entry.
283
+ - Add `machinalayout/react-native` subpath export.
284
+ - Add optional `react-native` peer metadata.
285
+ - Add initial RN adapter tests in isolated lane.
286
+
287
+ Prereqs from A0:
288
+
289
+ - Multi-entry build/export plumbing.
290
+
291
+ Status note (A1a, 2026-05-11): multi-entry dist output and subpath exports for existing modules (`./react`, `./text`, `./text/react`) are now being implemented while preserving root-import compatibility during `0.x`.
292
+
293
+ ### A2 — React Native text renderer
294
+
295
+ Scope:
296
+
297
+ - Add `src/text/react-native` renderer.
298
+ - Add `machinalayout/text/react-native` subpath export.
299
+ - Extend RN adapter test lane for text renderer behavior.
300
+
301
+ ### A3 — Vue layout adapter
302
+
303
+ Scope:
304
+
305
+ - Add `src/vue` adapter entry.
306
+ - Add `machinalayout/vue` subpath export.
307
+ - Add optional `vue` peer metadata.
308
+ - Add Vue adapter tests in isolated lane.
309
+
310
+ ### A4 — Vue text renderer
311
+
312
+ Scope:
313
+
314
+ - Add `src/text/vue` renderer.
315
+ - Add `machinalayout/text/vue` subpath export.
316
+ - Extend Vue test lane for text rendering behavior.
317
+
318
+ ### Later adapters
319
+
320
+ - SVG/debug renderer under dedicated subpaths.
321
+ - Svelte/Solid exploration after adapter API stabilization.
322
+
323
+ ## 13) Risks and mitigations
324
+
325
+ 1. **Root export bloat and accidental framework coupling**
326
+ - Mitigation: keep new adapters subpath-only; avoid root re-exports for new frameworks.
327
+
328
+ 2. **Peer dependency confusion**
329
+ - Mitigation: explicit matrix in README (adapter → required peer).
330
+
331
+ 3. **Build complexity regression**
332
+ - Mitigation: explicit multi-entry manifest + pack smoke checks per milestone.
333
+
334
+ 4. **CI/test instability from heavy adapter stacks**
335
+ - Mitigation: separate adapter test lanes and scoped test commands.
336
+
337
+ 5. **Future package split cost**
338
+ - Mitigation: enforce subpath discipline now so split is mostly import-path and publish-surface work later.
339
+
340
+ ## 14) Exact verification commands run
341
+
342
+ From repository root:
343
+
344
+ ```bash
345
+ npm test
346
+ npm run build
347
+ cd samples/control-room && npm run build
348
+ cd samples/music-player && npm run build
349
+ npm pack --dry-run
350
+ ```
351
+
352
+ Observed result in A0: all commands completed successfully in this environment.
@@ -0,0 +1,19 @@
1
+ # Adapter overview
2
+
3
+ Machina adapters ask you to learn one layout model: Machina records. The framework adapter only asks for components in that framework.
4
+
5
+ Layout geometry stays in `LayoutRow[]` + resolved rectangles from core APIs. Adapter differences are host-renderer details (DOM versus React Native style primitives), not separate layout dialects.
6
+
7
+ ## Adapter + text renderer matrix
8
+
9
+ | Target | Layout adapter | Text renderer | Required peer(s) | Notes |
10
+ | --- | --- | --- | --- | --- |
11
+ | React DOM | `machinalayout/react` | `machinalayout/text/react` | `react`, `react-dom` | Supports DOM containment/content-visibility and DOM wrapper hooks (`className`/`style`, attrs). |
12
+ | React Native | `machinalayout/react-native` | `machinalayout/text/react-native` | `react`, `react-native` | Uses numeric RN styles and RN primitives (`View`/`Text`); no DOM containment/content-visibility. |
13
+ | Vue DOM | `machinalayout/vue` | `machinalayout/text/vue` | `vue` | Adapter uses `h()` internally; users keep normal Vue components/templates as payloads. |
14
+
15
+ ## Import guidance
16
+
17
+ - Subpath imports are preferred for adapters/renderers: `machinalayout/react`, `machinalayout/react-native`, `machinalayout/vue`, `machinalayout/text`, `machinalayout/text/react`, `machinalayout/text/react-native`, and `machinalayout/text/vue`.
18
+ - Root imports remain valid during `0.x` compatibility windows.
19
+ - Framework peers are adapter-specific: install only peers needed by the subpaths you use.