machinalayout 0.1.0 → 0.3.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.
- package/README.md +295 -49
- package/dist/chunk-2ZQ2RFFI.js +400 -0
- package/dist/chunk-33CKBEJH.js +186 -0
- package/dist/chunk-BJOQRPPX.js +382 -0
- package/dist/chunk-KYWOCAHK.js +205 -0
- package/dist/chunk-RJYRJ3LD.js +0 -0
- package/dist/chunk-SVWYWI7I.js +59 -0
- package/dist/chunk-VREK57S3.js +13 -0
- package/dist/chunk-ZVDE7PX4.js +222 -0
- package/dist/debugOverlay-pJpj0n5H.d.ts +125 -0
- package/dist/deus/index.d.ts +14 -0
- package/dist/deus/index.js +26 -0
- package/dist/dispatch/index.d.ts +49 -0
- package/dist/dispatch/index.js +217 -0
- package/dist/handoff/index.d.ts +44 -0
- package/dist/handoff/index.js +83 -0
- package/dist/index.d.ts +54 -236
- package/dist/index.js +753 -583
- package/dist/inspect/index.d.ts +8 -0
- package/dist/inspect/index.js +97 -0
- package/dist/react/index.d.ts +41 -0
- package/dist/react/index.js +9 -0
- package/dist/react-native/index.d.ts +30 -0
- package/dist/react-native/index.js +84 -0
- package/dist/screenCatalog-ZjonGiOi.d.ts +46 -0
- package/dist/text/index.d.ts +10 -0
- package/dist/text/index.js +9 -0
- package/dist/text/react/index.d.ts +14 -0
- package/dist/text/react/index.js +7 -0
- package/dist/text/react-native/index.d.ts +16 -0
- package/dist/text/react-native/index.js +155 -0
- package/dist/text/vue/index.d.ts +113 -0
- package/dist/text/vue/index.js +202 -0
- package/dist/types-B90jb3RW.d.ts +184 -0
- package/dist/types-C4poVJpR.d.ts +74 -0
- package/dist/types-DLYAhNXw.d.ts +32 -0
- package/dist/vue/index.d.ts +173 -0
- package/dist/vue/index.js +112 -0
- package/docs/adapter-packaging-a0-plan.md +352 -0
- package/docs/adapters.md +19 -0
- package/docs/api-coherence-m8-audit.md +397 -0
- package/docs/deusmachina.md +108 -0
- package/docs/error-codes.md +95 -0
- package/docs/grid-arrange-m5a-contract.md +480 -0
- package/docs/grid-arrange.md +51 -0
- package/docs/inspection-and-handoff.md +126 -0
- package/docs/layout-interpolation.md +52 -0
- package/docs/machina-dispatch-d0-contract.md +496 -0
- package/docs/machina-dispatch.md +143 -0
- package/docs/named-layers.md +40 -0
- package/docs/react-adapter.md +63 -58
- package/docs/react-native-adapter.md +56 -0
- package/docs/react-native-text-renderer.md +50 -0
- package/docs/reference-alignment-m7a-contract.md +384 -0
- package/docs/reference-alignment.md +44 -0
- package/docs/responsive-variants.md +54 -0
- package/docs/screen-catalog-and-viewports.md +124 -0
- package/docs/stack-geometry-helpers.md +115 -0
- package/docs/vue-adapter.md +55 -0
- package/docs/vue-text-renderer.md +55 -0
- package/package.json +127 -60
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# MachinaLayout
|
|
2
2
|
|
|
3
|
-
MachinaLayout is a
|
|
3
|
+
MachinaLayout is a machine-native UI layout substrate: flat records in, deterministic rectangles out.
|
|
4
|
+
|
|
5
|
+
**CSS paints; Machina places.**
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -8,20 +10,125 @@ MachinaLayout is a framework-independent, machine-native layout system that reso
|
|
|
8
10
|
npm install machinalayout
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## One-page mental model
|
|
14
|
+
|
|
15
|
+
1. Author layout as flat `LayoutRow[]` records.
|
|
16
|
+
2. Parent means coordinate ownership.
|
|
17
|
+
3. `frame` decides a node rectangle.
|
|
18
|
+
4. `arrange` decides direct child placement.
|
|
19
|
+
5. Metadata (like `view`, `slot`, `z`, layers, data) shapes rendering behavior, not geometry solving.
|
|
20
|
+
6. Variants are authoring-time row selection.
|
|
21
|
+
7. The resolver outputs deterministic rectangles.
|
|
22
|
+
8. Adapters render those rectangles.
|
|
23
|
+
9. Text renders inside owned rectangles.
|
|
24
|
+
10. CSS paints; Machina places.
|
|
25
|
+
|
|
26
|
+
## Adapter philosophy
|
|
27
|
+
|
|
28
|
+
Machina adapters ask you to learn one layout model: Machina records. The framework adapter only asks for components in that framework.
|
|
29
|
+
|
|
30
|
+
- Machina adapters do not introduce a new layout model per framework.
|
|
31
|
+
- Layout stays framework-independent: author rows, resolve rectangles, render through adapters.
|
|
32
|
+
- Frameworks supply components; Machina supplies geometry.
|
|
33
|
+
- Users should not need framework-specific layout ceremony to place boxes.
|
|
34
|
+
- If you know TypeScript and what a component looks like in your renderer, that is enough.
|
|
35
|
+
- Adapter-specific details stay inside adapter internals.
|
|
36
|
+
|
|
37
|
+
**CSS paints; Machina places; adapters translate.**
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Adapter/text subpath matrix
|
|
41
|
+
|
|
42
|
+
### Layout adapters
|
|
43
|
+
|
|
44
|
+
- React DOM: `machinalayout/react`
|
|
45
|
+
- React Native: `machinalayout/react-native`
|
|
46
|
+
- Vue DOM: `machinalayout/vue`
|
|
47
|
+
|
|
48
|
+
### Text
|
|
49
|
+
|
|
50
|
+
- Parser/core text: `machinalayout/text`
|
|
51
|
+
|
|
52
|
+
### Text renderers
|
|
53
|
+
|
|
54
|
+
- React DOM: `machinalayout/text/react`
|
|
55
|
+
- React Native: `machinalayout/text/react-native`
|
|
56
|
+
- Vue DOM: `machinalayout/text/vue`
|
|
57
|
+
|
|
58
|
+
Inspection and handoff utilities are available at `machinalayout/inspect` and `machinalayout/handoff`.
|
|
59
|
+
|
|
60
|
+
Subpath imports are preferred for adapters/renderers. Root imports remain valid during `0.x` compatibility windows.
|
|
61
|
+
|
|
62
|
+
Framework peers are adapter-specific (`react`/`react-dom`, `react-native`, `vue`) based on the subpaths you use.
|
|
63
|
+
|
|
64
|
+
Normal users should not need to learn each framework's layout/template box-drawing system: layout is Machina records, framework components are payloads rendered inside resolved rectangles.
|
|
65
|
+
|
|
66
|
+
## Current capability summary
|
|
67
|
+
|
|
68
|
+
### Core
|
|
69
|
+
|
|
70
|
+
- `RootFrame`
|
|
71
|
+
- `AbsoluteFrame`
|
|
72
|
+
- `AnchorFrame` with `UiLength`
|
|
73
|
+
- `GuideFrame`
|
|
74
|
+
- `FixedFrame`
|
|
75
|
+
- `FillFrame`
|
|
76
|
+
- `CellFrame`
|
|
77
|
+
- `StackArrange`
|
|
78
|
+
- `GridArrange`
|
|
79
|
+
- `OffsetSpec`
|
|
80
|
+
- responsive variants
|
|
81
|
+
- bounded `z`
|
|
82
|
+
- named layers
|
|
83
|
+
- layout interpolation helpers
|
|
84
|
+
- stack geometry/content query helpers
|
|
85
|
+
|
|
86
|
+
### React
|
|
87
|
+
|
|
88
|
+
- `MachinaReactView`
|
|
89
|
+
- effective render key: `view ?? slot`
|
|
90
|
+
- `viewData` / `nodeData`
|
|
91
|
+
- named layer paint ordering
|
|
92
|
+
- containment/content-visibility options
|
|
93
|
+
|
|
94
|
+
### Vue
|
|
12
95
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
96
|
+
- `MachinaVueView`
|
|
97
|
+
- same resolved-layout rectangle rendering model as React DOM
|
|
98
|
+
- effective render key: `view ?? slot`
|
|
99
|
+
- `viewData` / `nodeData`
|
|
100
|
+
- named layer paint ordering
|
|
101
|
+
- containment/content-visibility options
|
|
17
102
|
|
|
18
|
-
|
|
103
|
+
### Text
|
|
19
104
|
|
|
20
|
-
|
|
105
|
+
- MachinaText parser
|
|
106
|
+
- diagnostics
|
|
107
|
+
- `MachinaTextView`
|
|
108
|
+
- vertical rhythm policy
|
|
21
109
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
110
|
+
### Sharp boundaries
|
|
111
|
+
|
|
112
|
+
- No portals/reparenting.
|
|
113
|
+
- No intrinsic text sizing driving outer layout.
|
|
114
|
+
- No general constraint solver.
|
|
115
|
+
- No CSS Grid clone.
|
|
116
|
+
- No auto-placement.
|
|
117
|
+
|
|
118
|
+
`GuideFrame` reads other nodes’ resolved geometry as a read-only alignment input. It preserves the one-parent model: parent remains the coordinate owner. `GuideFrame` does not portal, reparent DOM nodes, or escape clipping.
|
|
119
|
+
|
|
120
|
+
Named layers organize paint order over the existing bounded `z` system. Layers are not portals.
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Docs index
|
|
124
|
+
|
|
125
|
+
- [Row model](docs/row-model.md)
|
|
126
|
+
- [Frames and stack](docs/frames-and-stack.md)
|
|
127
|
+
- [Grid arrange](docs/grid-arrange.md)
|
|
128
|
+
- [Stack geometry helpers](docs/stack-geometry-helpers.md)
|
|
129
|
+
- [Screen catalog and viewport matrix](docs/screen-catalog-and-viewports.md)
|
|
130
|
+
- [Inspection and handoff bundles](docs/inspection-and-handoff.md)
|
|
131
|
+
- [Error codes](docs/error-codes.md)
|
|
25
132
|
|
|
26
133
|
## Tiny `LayoutRow[]` example
|
|
27
134
|
|
|
@@ -42,14 +149,14 @@ const rows: LayoutRow[] = [
|
|
|
42
149
|
parent: "root",
|
|
43
150
|
order: 0,
|
|
44
151
|
frame: { kind: "anchor", left: 0, right: 0, top: 0, height: 64 },
|
|
45
|
-
|
|
152
|
+
view: "header",
|
|
46
153
|
},
|
|
47
154
|
{
|
|
48
155
|
id: "sidebar",
|
|
49
156
|
parent: "root",
|
|
50
157
|
order: 1,
|
|
51
158
|
frame: { kind: "anchor", left: 0, top: 64, bottom: 0, width: 240 },
|
|
52
|
-
|
|
159
|
+
view: "sidebar",
|
|
53
160
|
},
|
|
54
161
|
{
|
|
55
162
|
id: "toolbar",
|
|
@@ -70,7 +177,7 @@ const rows: LayoutRow[] = [
|
|
|
70
177
|
parent: "toolbar",
|
|
71
178
|
order: 0,
|
|
72
179
|
frame: { kind: "fixed", width: 120, height: 40 },
|
|
73
|
-
|
|
180
|
+
view: "toolbarButton",
|
|
74
181
|
},
|
|
75
182
|
];
|
|
76
183
|
|
|
@@ -78,12 +185,18 @@ const rootRect: Rect = { x: 0, y: 0, width: 1024, height: 640 };
|
|
|
78
185
|
const resolved = resolveLayoutRows(rows, rootRect);
|
|
79
186
|
```
|
|
80
187
|
|
|
188
|
+
`view` is the preferred author-facing render key. `slot` remains valid as the adapter-facing technical key. The effective render key is `view ?? slot`.
|
|
189
|
+
|
|
81
190
|
## React adapter quick example
|
|
82
191
|
|
|
83
192
|
```tsx
|
|
84
|
-
import {
|
|
193
|
+
import { resolveLayoutRows } from "machinalayout";
|
|
194
|
+
import { MachinaReactView } from "machinalayout/react";
|
|
195
|
+
import { parseMachinaText } from "machinalayout/text";
|
|
196
|
+
import { MachinaTextView } from "machinalayout/text/react";
|
|
85
197
|
|
|
86
198
|
const resolved = resolveLayoutRows(rows, rootRect);
|
|
199
|
+
const textAst = parseMachinaText("Hello");
|
|
87
200
|
|
|
88
201
|
const views = {
|
|
89
202
|
header: HeaderView,
|
|
@@ -96,60 +209,193 @@ export function App() {
|
|
|
96
209
|
}
|
|
97
210
|
```
|
|
98
211
|
|
|
99
|
-
## Sample demo
|
|
100
212
|
|
|
101
|
-
|
|
213
|
+
Subpath imports are the preferred path for adapters (`machinalayout/react`, `machinalayout/react-native`, `machinalayout/vue`, `machinalayout/text`, `machinalayout/text/react`, `machinalayout/text/react-native`, `machinalayout/text/vue`).
|
|
102
214
|
|
|
103
|
-
|
|
215
|
+
`machinalayout/react-native` and `machinalayout/text/react-native` require the `react-native` peer dependency in your app, and `machinalayout/vue` / `machinalayout/text/vue` require the `vue` peer dependency in your app. Root imports remain valid for compatibility during `0.x`.
|
|
104
216
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
217
|
+
## Unified adapter usage pattern
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { resolveLayoutRows, type LayoutRow } from "machinalayout";
|
|
221
|
+
|
|
222
|
+
const rows: LayoutRow[] = [
|
|
223
|
+
{ id: "root", frame: { kind: "root" } },
|
|
224
|
+
{
|
|
225
|
+
id: "sidebar",
|
|
226
|
+
parent: "root",
|
|
227
|
+
frame: { kind: "anchor", left: 0, top: 0, bottom: 0, width: 240 },
|
|
228
|
+
view: "Sidebar",
|
|
229
|
+
},
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
const layout = resolveLayoutRows(rows, { x: 0, y: 0, width: 1200, height: 800 });
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
import { MachinaReactView } from "machinalayout/react";
|
|
237
|
+
const views = { Sidebar };
|
|
238
|
+
<MachinaReactView layout={layout} views={views} />;
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { MachinaReactNativeView } from "machinalayout/react-native";
|
|
243
|
+
const views = { Sidebar };
|
|
244
|
+
<MachinaReactNativeView layout={layout} views={views} />;
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```vue
|
|
248
|
+
<script setup lang="ts">
|
|
249
|
+
import { MachinaVueView } from "machinalayout/vue";
|
|
250
|
+
const views = { Sidebar };
|
|
251
|
+
</script>
|
|
252
|
+
|
|
253
|
+
<template>
|
|
254
|
+
<MachinaVueView :layout="layout" :views="views" />
|
|
255
|
+
</template>
|
|
109
256
|
```
|
|
110
257
|
|
|
111
|
-
|
|
258
|
+
Keep `views` stable (component references), and send changing data through `viewData` / `nodeData`:
|
|
112
259
|
|
|
113
|
-
|
|
260
|
+
```tsx
|
|
261
|
+
const views = { Inspector };
|
|
262
|
+
|
|
263
|
+
<MachinaReactView
|
|
264
|
+
layout={layout}
|
|
265
|
+
views={views}
|
|
266
|
+
viewData={{ Inspector: inspectorData }}
|
|
267
|
+
/>;
|
|
268
|
+
```
|
|
114
269
|
|
|
115
|
-
|
|
270
|
+
```tsx
|
|
271
|
+
const views = {
|
|
272
|
+
Inspector: () => <Inspector value={value} />,
|
|
273
|
+
};
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Public API index
|
|
277
|
+
|
|
278
|
+
### Core authoring/types
|
|
279
|
+
|
|
280
|
+
- `LayoutRow`
|
|
281
|
+
- `FrameSpec`
|
|
282
|
+
- `ArrangeSpec`
|
|
283
|
+
- `UiLength`
|
|
284
|
+
- `OffsetSpec`
|
|
285
|
+
|
|
286
|
+
### Frames
|
|
287
|
+
|
|
288
|
+
- `RootFrame`
|
|
116
289
|
- `AbsoluteFrame`
|
|
117
290
|
- `AnchorFrame`
|
|
291
|
+
- `GuideFrame`
|
|
118
292
|
- `FixedFrame`
|
|
119
|
-
- `FillFrame`
|
|
293
|
+
- `FillFrame`
|
|
294
|
+
- `CellFrame`
|
|
295
|
+
|
|
296
|
+
### Arrangers
|
|
297
|
+
|
|
120
298
|
- `StackArrange`
|
|
121
|
-
-
|
|
122
|
-
|
|
299
|
+
- `GridArrange`
|
|
300
|
+
|
|
301
|
+
### Core functions
|
|
302
|
+
|
|
303
|
+
- `compileLayoutRows`
|
|
304
|
+
- `selectLayoutRowsForRoot`
|
|
305
|
+
- `resolveLayoutRows`
|
|
306
|
+
- `resolveLayoutDocument`
|
|
307
|
+
- `resolveFrame`
|
|
308
|
+
- `lerpResolvedLayouts`
|
|
309
|
+
|
|
310
|
+
### Resolved helpers
|
|
311
|
+
|
|
312
|
+
- `toResolvedTree`
|
|
313
|
+
- `flattenResolvedTree`
|
|
314
|
+
- `formatRect`
|
|
315
|
+
|
|
316
|
+
### React
|
|
317
|
+
|
|
318
|
+
- `MachinaReactView`
|
|
319
|
+
- `MachinaReactViewProps`
|
|
320
|
+
- `MachinaSlotProps`
|
|
321
|
+
- `MachinaRenderLayer`
|
|
123
322
|
|
|
124
|
-
|
|
323
|
+
### Text
|
|
125
324
|
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
325
|
+
- `parseMachinaText`
|
|
326
|
+
- `MachinaTextView`
|
|
327
|
+
- `MachinaTextSpec`
|
|
328
|
+
- `MachinaTextDocument`
|
|
329
|
+
|
|
330
|
+
### Error
|
|
331
|
+
|
|
332
|
+
- `MachinaLayoutError`
|
|
333
|
+
- `MachinaLayoutErrorCode`
|
|
334
|
+
|
|
335
|
+
## Sample demos
|
|
336
|
+
|
|
337
|
+
- [`samples/control-room`](samples/control-room/README.md)
|
|
338
|
+
- [`samples/music-player`](samples/music-player/README.md)
|
|
339
|
+
- [`samples/dispatch-counter`](samples/dispatch-counter/README.md)
|
|
340
|
+
|
|
341
|
+
Run it locally:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
cd samples/control-room
|
|
345
|
+
npm install
|
|
346
|
+
npm run dev
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Formatting
|
|
350
|
+
|
|
351
|
+
This repo uses Biome.
|
|
352
|
+
|
|
353
|
+
- `npm run format` rewrites files.
|
|
354
|
+
- `npm run format:check` checks formatting.
|
|
355
|
+
- `npm run lint` runs Biome lint rules.
|
|
356
|
+
- Generated `dist/` is ignored by Biome.
|
|
134
357
|
|
|
135
358
|
## Documentation
|
|
136
359
|
|
|
360
|
+
### Milestones and audits
|
|
361
|
+
|
|
137
362
|
- [M0 contract](docs/m0-contract.md)
|
|
138
|
-
- [
|
|
139
|
-
- [
|
|
140
|
-
- [
|
|
141
|
-
- [
|
|
142
|
-
- [
|
|
363
|
+
- [M1/M2 MachinaText plan notes](docs/machina-text-m2a-plan.md)
|
|
364
|
+
- [M2z npm prepublish audit](docs/npm-prepublish-m2z-audit.md)
|
|
365
|
+
- [M3c npm cleanup audit](docs/npm-prepublish-m3c-cleanup.md)
|
|
366
|
+
- [M4 interpolation guide](docs/layout-interpolation.md)
|
|
367
|
+
- [M5a GridArrange design contract](docs/grid-arrange-m5a-contract.md)
|
|
368
|
+
- [M7a reference alignment design contract](docs/reference-alignment-m7a-contract.md)
|
|
369
|
+
- [M8 API coherence audit](docs/api-coherence-m8-audit.md)
|
|
370
|
+
- [A0 adapter packaging plan](docs/adapter-packaging-a0-plan.md)
|
|
143
371
|
|
|
372
|
+
### Core layout model
|
|
144
373
|
|
|
145
|
-
|
|
374
|
+
- [Row model](docs/row-model.md)
|
|
375
|
+
- [Frames and stack](docs/frames-and-stack.md)
|
|
376
|
+
- [Grid arrange runtime guide](docs/grid-arrange.md)
|
|
377
|
+
- [Reference alignment runtime guide](docs/reference-alignment.md)
|
|
378
|
+
- [Responsive variants](docs/responsive-variants.md)
|
|
379
|
+
- [Named layers](docs/named-layers.md)
|
|
380
|
+
- [Layout interpolation](docs/layout-interpolation.md)
|
|
146
381
|
|
|
147
|
-
|
|
382
|
+
### Adapters and text
|
|
148
383
|
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
384
|
+
- [Adapter overview](docs/adapters.md)
|
|
385
|
+
- [React adapter boundary](docs/react-adapter.md)
|
|
386
|
+
- [React Native adapter](docs/react-native-adapter.md)
|
|
387
|
+
- [Vue adapter](docs/vue-adapter.md)
|
|
388
|
+
- [A0 adapter packaging plan](docs/adapter-packaging-a0-plan.md)
|
|
389
|
+
- [MachinaText parser](docs/machina-text-parser.md)
|
|
390
|
+
- [MachinaText React renderer](docs/machina-text-react.md)
|
|
391
|
+
- [MachinaText React Native renderer](docs/react-native-text-renderer.md)
|
|
392
|
+
- [MachinaText Vue renderer](docs/vue-text-renderer.md)
|
|
152
393
|
|
|
153
|
-
|
|
394
|
+
### Boundaries and diagnostics
|
|
154
395
|
|
|
155
|
-
-
|
|
396
|
+
- [Forbidden concepts](docs/forbidden-concepts.md)
|
|
397
|
+
- [Z-order and containment](docs/z-order-and-containment.md)
|
|
398
|
+
- [Error code reference](docs/error-codes.md)
|
|
399
|
+
- [MachinaDispatch runtime guide](docs/machina-dispatch.md)
|
|
400
|
+
- [DeusMachina behavioral kernel](docs/deusmachina.md)
|
|
401
|
+
- Dispatch sample: [`samples/dispatch-counter`](samples/dispatch-counter/README.md) (uses `machinalayout/dispatch`)
|