@liquidcars/atlas-layout 0.1.9 → 0.1.10

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 CHANGED
@@ -134,13 +134,15 @@ relations:
134
134
  from: source
135
135
  to: rules
136
136
  label: feeds
137
+ text: Sends normalized source data to the rules engine.
138
+ url: https://example.com/relations/source-to-rules
137
139
  mode: bidirectional
138
140
  - from: rules
139
141
  to: output
140
142
  mode: broken
141
143
  ```
142
144
 
143
- `mode` es la forma recomendada y el compilador siempre la emite normalizada. Para facilitar la migración se aceptan también `visual`, `render`, `type`, `direction`, `bidirectional: true` y `broken: true`, además de los alias `two-way`, `both` e `interrupted`. La forma abreviada puede incluir el modo como cuarto valor: `[from, to, label, mode]`. Un modo desconocido conserva la relación como `directed` y añade el diagnóstico `UNKNOWN_RELATION_MODE`.
145
+ `label` es el título corto visible junto a la conexión, `text` permite documentar su significado y `url` enlaza documentación externa desde el panel de información. `mode` es la forma recomendada y el compilador siempre la emite normalizada. Para facilitar la migración se aceptan también `visual`, `render`, `type`, `direction`, `bidirectional: true` y `broken: true`, además de los alias `two-way`, `both` e `interrupted`. La forma abreviada puede incluir el modo como cuarto valor: `[from, to, label, mode]`. Un modo desconocido conserva la relación como `directed` y añade el diagnóstico `UNKNOWN_RELATION_MODE`.
144
146
 
145
147
  En un documento Markdown dividido, el bloque de relaciones contiene una lista YAML:
146
148
 
@@ -194,4 +196,4 @@ El resultado mantiene `palette`, `theme`, `entities` y `relations`, con `p` y `s
194
196
 
195
197
  El espacio de una celda y el tamaño de la geometría son conceptos distintos. Cuando el layout asigna una celda rectangular a una geometría sin `size` explícito, la figura se centra y se escala uniformemente para caber en el menor volumen compatible; no se estira por separado en `x`, `y` y `z`. Por eso una esfera conserva `s[0] === s[1] === s[2]`, aunque su celda sea rectangular. Un `size` explícito sigue teniendo prioridad y permite al autor solicitar una proporción concreta.
196
198
 
197
- `row`, `grid`/`masonry` y `volume` producen posiciones deterministas. Las constraints de tamaño y alineación, el empaquetado compacto, los grupos virtuales y la distribución `justify` forman parte del contrato estable de autoría. El algoritmo `graph` sigue reservado: por ahora emite `GRAPH_LAYOUT_FALLBACK` y usa `grid`. La proyección y el enrutado avanzado de relaciones entre contenedores permanecen como líneas de desarrollo posteriores.
199
+ `row`, `grid`/`masonry` y `volume` producen posiciones deterministas. `variant: masonry` desplaza las filas alternas media celda sin exigir una sección `stagger`; `stagger.offset` queda disponible como override explícito. Para conservar legibilidad frontal se recomienda `plane: xy`, y para una composición lateral, `plane: yz`. Las constraints de tamaño y alineación, el empaquetado compacto, los grupos virtuales y la distribución `justify` forman parte del contrato estable de autoría. El algoritmo `graph` sigue reservado: por ahora emite `GRAPH_LAYOUT_FALLBACK` y usa `grid`. La proyección y el enrutado avanzado de relaciones entre contenedores permanecen como líneas de desarrollo posteriores.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquidcars/atlas-layout",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Declarative layout compiler for LiquidCars Atlas models",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -47,7 +47,7 @@ subject to sizeMode and diagnostics.
47
47
 
48
48
  Required: id.
49
49
 
50
- Common fields: name, sub, text, type, parent, children, geometry, geometryOptions,
50
+ Common fields: name, sub, text, url, type, parent, children, geometry, geometryOptions,
51
51
  geometryPalette, style, layout, weight, span, size, sizeMode, p, s, c and radius.
52
52
 
53
53
  An entity with children is a container and must explicitly declare `type: container`.
@@ -73,7 +73,10 @@ fit permits assisted layout to use the geometry's canonical size.
73
73
 
74
74
  layout.algorithm accepts row, grid, volume or graph. direction accepts x, y or z.
75
75
  Grid layouts also accept variant uniform or masonry, optional columns and rows, and
76
- a plane of xz (the default), xy or yz. Volume layouts additionally accept layers.
76
+ a plane of xz (the default), xy or yz. Masonry offsets alternate rows by half a cell
77
+ unless `stagger.offset` explicitly overrides that distance. Use plane xy for layouts
78
+ intended to remain legible from the natural frontal camera, or yz for a lateral view.
79
+ Volume layouts additionally accept layers.
77
80
  gap and padding are absolute numbers. justify accepts start, center, end,
78
81
  space-between, space-around or space-evenly. These modes become distinct when a
79
82
  row receives an explicit or constrained size. Distributed modes treat gap as the
@@ -145,7 +148,10 @@ constraints:
145
148
 
146
149
  Relations require from and to entity ids. mode is directed, bidirectional or broken.
147
150
  The aliases visual, render, type and direction are accepted for compatibility.
148
- Optional fields include id, label, fromAnchor, toAnchor, priority and layout.
151
+ Optional fields include id, label, text, url, fromAnchor, toAnchor, priority and layout.
152
+ `label` is the compact caption associated with the connection; `text` is its longer
153
+ description and `url` links to external documentation when the relation is selected
154
+ in the information panel.
149
155
 
150
156
  ## Rendering
151
157
 
package/src/index.js CHANGED
@@ -242,6 +242,8 @@ function normalizeRelations(input, validIds, diagnostics) {
242
242
  index
243
243
  };
244
244
  if (relation.id != null) normalized.id = String(relation.id);
245
+ if (relation.text != null) normalized.text = String(relation.text);
246
+ if (relation.url != null) normalized.url = String(relation.url);
245
247
  if (relation.fromAnchor != null || relation.from_anchor != null) normalized.fromAnchor = String(relation.fromAnchor ?? relation.from_anchor);
246
248
  if (relation.toAnchor != null || relation.to_anchor != null) normalized.toAnchor = String(relation.toAnchor ?? relation.to_anchor);
247
249
  return [normalized];
@@ -890,7 +892,12 @@ function packedGridLayout(items, spec, diagnostics, dimension = 2) {
890
892
  for (const item of placements) {
891
893
  const columnSize = item.span[0] * columnCell + (item.span[0] - 1) * gap;
892
894
  const rowSize = item.span[1] * rowCell + (item.span[1] - 1) * gap;
893
- const offset = spec.variant === "masonry" && item.cell[1] % 2 === 1 ? (spec.stagger?.offset === "half-cell" ? (columnCell + gap) / 2 : scalar(spec.stagger?.offset, 0)) : 0;
895
+ const staggerOffset = spec.stagger?.offset;
896
+ const offset = spec.variant === "masonry" && item.cell[1] % 2 === 1
897
+ ? (staggerOffset == null || staggerOffset === "half-cell"
898
+ ? (columnCell + gap) / 2
899
+ : scalar(staggerOffset, 0))
900
+ : 0;
894
901
  const slotSize = [0, 0, 0];
895
902
  slotSize[columnAxis] = columnSize;
896
903
  slotSize[rowAxis] = rowSize;
package/src/spec.js CHANGED
@@ -30,6 +30,7 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
30
30
  name: field("Visible title.", null, { type: "string" }),
31
31
  sub: field("Visible subtitle.", null, { type: "string" }),
32
32
  text: field("Description shown by the inspector.", null, { type: "string" }),
33
+ url: field("External documentation opened from the inspector.", null, { type: "url" }),
33
34
  type: field("Structural role. Use container when declaring children; omit it for a leaf item.", ["container"]),
34
35
  parent: field("Parent entity id.", null, { type: "string", authoring: "absolute" }),
35
36
  children: field("Nested entities.", null, { context: "entity", sequence: true }),
@@ -56,6 +57,8 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
56
57
  from: field("Source entity id.", null, { type: "string", required: true }),
57
58
  to: field("Target entity id.", null, { type: "string", required: true }),
58
59
  label: field("Text shown on the relation.", null, { type: "string" }),
60
+ text: field("Description shown by the inspector.", null, { type: "string" }),
61
+ url: field("External documentation opened from the inspector.", null, { type: "url" }),
59
62
  mode: field("Canonical visual relation mode.", ["directed", "bidirectional", "broken"]),
60
63
  visual: field("Historical alias for relation mode.", ["directed", "bidirectional", "broken"]),
61
64
  fromAnchor: field("Named source anchor.", null, { type: "string" }),
@@ -69,7 +72,7 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
69
72
  properties: freeze({
70
73
  algorithm: field("Spatial strategy.", ["row", "grid", "volume", "graph"]),
71
74
  direction: field("Primary semantic axis.", ["x", "y", "z"]),
72
- variant: field("Regular or staggered grid cells.", ["uniform", "masonry"]),
75
+ variant: field("Regular cells or masonry rows staggered by half a cell by default.", ["uniform", "masonry"]),
73
76
  plane: field("Axes used by a two-dimensional grid.", ["xz", "xy", "yz"]),
74
77
  packing: field("Preserve initial slots or compact free space after constraints.", ["preserve", "compact"]),
75
78
  groups: field("Invisible sibling groups used only during layout.", null, { context: "layoutGroup", sequence: true }),
@@ -79,7 +82,7 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
79
82
  gap: field("Spacing between children.", null, { type: "number" }),
80
83
  padding: field("Spacing to the container boundary.", null, { type: "number" }),
81
84
  justify: field("Row alignment or distribution within an assigned size.", ["start", "center", "end", "space-between", "space-around", "space-evenly"]),
82
- stagger: field("Optional masonry offset.", null, { context: "stagger" }),
85
+ stagger: field("Optional override for the masonry row offset.", null, { context: "stagger" }),
83
86
  constraints: field("Equal-size and edge-alignment rules for this layout's siblings.", null, { context: "constraint", sequence: true })
84
87
  })
85
88
  }),
@@ -169,7 +172,7 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
169
172
  stagger: freeze({
170
173
  label: "Stagger",
171
174
  properties: freeze({
172
- offset: field("Masonry row offset.", ["half-cell"], { type: "string" })
175
+ offset: field("Masonry row offset; defaults to half-cell.", ["half-cell"], { type: "string" })
173
176
  })
174
177
  }),
175
178
  label: freeze({ label: "Label appearance", properties: freeze({ color: field("Label colour.", null, { valueSource: "palette" }), opacity: field("Label opacity.", null, { type: "number" }) }) }),