@liquidcars/atlas-layout 0.1.14 → 0.1.15

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
@@ -135,6 +135,26 @@ layout:
135
135
  ```
136
136
  ````
137
137
 
138
+ Las etiquetas de los elementos se colocan debajo por defecto. El modelo puede
139
+ cambiar esa política de forma heredable mediante `style.label.anchor`; una
140
+ entidad concreta puede sobrescribirla con la misma propiedad. Los títulos de
141
+ los contenedores conservan su colocación automática salvo que el contenedor
142
+ declare un anclaje explícito:
143
+
144
+ ```yaml
145
+ style:
146
+ label:
147
+ anchor: bottom
148
+ entities:
149
+ - id: source
150
+ geometry: sphere
151
+ - id: exceptional
152
+ geometry: box
153
+ style:
154
+ label:
155
+ anchor: top
156
+ ```
157
+
138
158
  Las relaciones admiten el modo visual canónico `directed`, `bidirectional` o `broken`:
139
159
 
140
160
  ```yaml
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquidcars/atlas-layout",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Declarative layout compiler for LiquidCars Atlas models",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -5,7 +5,7 @@ The executable projection of this contract is packages/atlas-layout/src/spec.js.
5
5
 
6
6
  ## Root model
7
7
 
8
- A model may contain version, palette, theme, render, layout, entities and relations.
8
+ A model may contain version, palette, theme, style, render, layout, entities and relations.
9
9
  Entities may be declared at the root or nested under children. The compiler normalizes
10
10
  nested entities to a flat list with parent references.
11
11
 
@@ -189,7 +189,9 @@ in the information panel.
189
189
  ## Rendering
190
190
 
191
191
  palette maps tokens to CSS colours. style.color or c can reference a token or direct
192
- CSS colour. render can additionally set relationMode, selectionMode, toolbar,
192
+ CSS colour. At model level, `style.label.anchor` supplies the inherited item-label
193
+ position and defaults to `bottom`; an entity may override it. Container titles stay
194
+ automatic unless their entity declares an explicit label anchor. render can additionally set relationMode, selectionMode, toolbar,
193
195
  shellLabels (the text-label contrast outline), focus and camera. `render.focus`
194
196
  accepts `mode: all|connected`, `effect: dim|hide`, `layout: preserve|reflow`
195
197
  and an optional dim `opacity`. Connected focus retains the selection, its directly
package/src/index.js CHANGED
@@ -6,6 +6,10 @@ import atlasLayoutPackage from "../package.json" with { type: "json" };
6
6
  export const ATLAS_LAYOUT_VERSION = atlasLayoutPackage.version;
7
7
 
8
8
  const DEFAULT_COLOR = "#b9d8eb";
9
+ const DEFAULT_LABEL_ANCHOR = "bottom";
10
+ const DEFAULT_MODEL_STYLE = Object.freeze({
11
+ label: Object.freeze({ anchor: DEFAULT_LABEL_ANCHOR })
12
+ });
9
13
 
10
14
  const DEFAULT_SIZES = Object.freeze({
11
15
  box: [2.5, 1.2, 2.2],
@@ -284,7 +288,7 @@ function resolveColor(value, inherited, palette, diagnostics, entityId) {
284
288
  return palette.default_color;
285
289
  }
286
290
 
287
- function resolveStyles(entities, sourceById, childrenById, palette, diagnostics) {
291
+ function resolveStyles(entities, sourceById, childrenById, palette, diagnostics, modelStyle) {
288
292
  const byId = new Map(entities.map(entity => [entity.id, entity]));
289
293
  const resolved = new Map();
290
294
 
@@ -296,12 +300,15 @@ function resolveStyles(entities, sourceById, childrenById, palette, diagnostics)
296
300
  style.color = resolveColor(style.color, parentStyle.color, palette, diagnostics, id);
297
301
  entity.style = style;
298
302
  entity.c = style.color;
303
+ const authoredLabelAnchor = source.style?.label?.anchor ?? source.labelAnchor ?? source.label_anchor;
304
+ if (authoredLabelAnchor != null) entity.labelAnchor = String(authoredLabelAnchor);
305
+ else if (!isContainerType(entity.type) && style.label?.anchor != null) entity.labelAnchor = String(style.label.anchor);
299
306
  if (style.radius != null && entity.radius == null) entity.radius = scalar(style.radius, 0);
300
307
  resolved.set(id, style);
301
308
  for (const childId of childrenById.get(id) || []) visit(childId, style);
302
309
  }
303
310
 
304
- for (const entity of entities) if (!entity.parent) visit(entity.id);
311
+ for (const entity of entities) if (!entity.parent) visit(entity.id, modelStyle);
305
312
  return resolved;
306
313
  }
307
314
 
@@ -1843,7 +1850,9 @@ function compileResolvedAtlasModel(input, options = {}) {
1843
1850
  if (!flat.entities.length) diagnostic(diagnostics, "fatal", "NO_VALID_ENTITIES", "The model does not contain any valid entities.");
1844
1851
  const validIds = new Set(flat.entities.map(entity => entity.id));
1845
1852
  const relations = normalizeRelations(source.relations, validIds, diagnostics);
1846
- resolveStyles(flat.entities, flat.sourceById, flat.childrenById, palette, diagnostics);
1853
+ const modelStyle = mergeStyle(DEFAULT_MODEL_STYLE, source.style || {});
1854
+ if (!Object.keys(modelStyle.edges || {}).length) delete modelStyle.edges;
1855
+ resolveStyles(flat.entities, flat.sourceById, flat.childrenById, palette, diagnostics, modelStyle);
1847
1856
  const byId = new Map(flat.entities.map(entity => [entity.id, entity]));
1848
1857
  const graphContext = { relations, byId };
1849
1858
  graphContext.graphOrderHints = globalGraphOrderHints(source, flat, relations, byId);
@@ -1906,6 +1915,7 @@ function compileResolvedAtlasModel(input, options = {}) {
1906
1915
  const output = {
1907
1916
  palette,
1908
1917
  theme: resolveTheme(source),
1918
+ style: modelStyle,
1909
1919
  entities: flat.entities.map(entity => {
1910
1920
  const copy = { ...entity };
1911
1921
  delete copy.style;
@@ -1960,4 +1970,4 @@ export function compileAtlasModelWithDiagnostics(input, options = {}) {
1960
1970
  return { model, diagnostics: model.diagnostics || [] };
1961
1971
  }
1962
1972
 
1963
- export const layoutDefaults = Object.freeze({ defaultColor: DEFAULT_COLOR, sizes: DEFAULT_SIZES, aspectFactors: ASPECT_FACTORS });
1973
+ export const layoutDefaults = Object.freeze({ defaultColor: DEFAULT_COLOR, labelAnchor: DEFAULT_LABEL_ANCHOR, sizes: DEFAULT_SIZES, aspectFactors: ASPECT_FACTORS });
package/src/spec.js CHANGED
@@ -17,6 +17,7 @@ export const ATLAS_LAYOUT_SPEC_V1 = freeze({
17
17
  palette: field("Named model colours.", null, { context: "palette" }),
18
18
  theme: field("Renderer theme configuration.", null, { context: "theme" }),
19
19
  render: field("Renderer configuration.", null, { context: "render" }),
20
+ style: field("Inherited model appearance defaults.", null, { context: "style" }),
20
21
  layout: field("Assisted layout for root entities.", null, { context: "layout" }),
21
22
  constraints: field("Equal-size and edge-alignment rules for root siblings.", null, { context: "constraint", sequence: true }),
22
23
  entities: field("Top-level entities and containers.", null, { context: "entity", sequence: true }),