@formicoidea/labre-framework-edgy 0.42.0 → 0.43.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/dist/consts.d.ts CHANGED
@@ -38,17 +38,34 @@ export declare const FONT_FAMILY = "Inter, sans-serif";
38
38
  * Uniform fit of the reference design into an element of size `w × h`: the
39
39
  * scale factor plus the centering offsets (letterboxed). Shared by the renderer
40
40
  * (to draw) and the view (to map clicks back into reference coords).
41
+ *
42
+ * The fit itself is the library's ({@link fitReference}, R37): only the
43
+ * reference size is this framework's business.
41
44
  */
42
- export declare function refScale(w: number, h: number): {
43
- s: number;
44
- ox: number;
45
- oy: number;
46
- };
45
+ export declare function refScale(w: number, h: number): import("@formicoidea/labre-core/_pkgs/affine-block-surface").RefFit;
47
46
  /**
48
- * Bounding box of the three circles in reference coords (small padding). The
49
- * REF margins around it only exist for the facet name labels — when a diagram
50
- * hides them (`cropToCircles`), the renderer fits THIS box into the element
51
- * bounds instead, so the background hugs the Venn.
47
+ * Bounding box of the three circles in reference coords, with just enough
48
+ * padding to see their outline. When a diagram hides its facet names
49
+ * (`cropToCircles` without `showLabels`) the renderer fits THIS box into the
50
+ * element bounds, so the background hugs the Venn.
51
+ *
52
+ * ## Why the padding is 2.5 and not the 8 it was
53
+ *
54
+ * The padding is the ONLY empty band such a board has, and it is spent at the
55
+ * element's scale, not at the reference one. The EDGY dynamic template draws
56
+ * its board at `DYN_SCALE = 4.8`, so eight reference units of padding were
57
+ * **32.4 model units** of nothing on each of the four sides — the board a user
58
+ * has to catch by its border (R37) sat a good inch away from the circles, which
59
+ * is what the recette of 23/09/2026 reported. 2.5 leaves 1.25 past the circles'
60
+ * own 2.5-wide outline, i.e. 6 model units at the dynamic board's scale and
61
+ * under 2 at a facets board's.
62
+ *
63
+ * `templates/dynamic.ts` places every element of the dynamic board in
64
+ * coordinates relative to this box (`dynToModel`) and sizes the board from it,
65
+ * so the template follows in the same breath: both are derived here, and a
66
+ * freshly inserted template is aligned by construction. A board built from the
67
+ * OLD template keeps its `xywh` and sees the Venn grow 3.8 % inside it — see
68
+ * the changeset.
52
69
  */
53
70
  export declare const CROP: {
54
71
  x: number;
@@ -58,8 +75,8 @@ export declare const CROP: {
58
75
  };
59
76
  /**
60
77
  * Crop box KEEPING room for the three facet name labels (drawn outside the
61
- * circles): the circles box plus a fixed text allowance left/right and below.
62
- * Used when a cropped diagram still shows its labels.
78
+ * circles): the circles plus {@link LABEL_ALLOWANCE}, which is asymmetric
79
+ * because the words are. Used when a cropped diagram still shows its labels.
63
80
  */
64
81
  export declare const CROP_LABELED: {
65
82
  x: number;
package/dist/consts.js CHANGED
@@ -6,6 +6,7 @@
6
6
  * uniformly to the element bounds — so the three circles always stay circular
7
7
  * and the pictos/labels keep their relative proportions at any size.
8
8
  */
9
+ import { refScale as fitReference } from '@formicoidea/labre-core/blocks/surface';
9
10
  /** Reference design size (the validated mockup canvas). */
10
11
  export const REF_W = 680;
11
12
  export const REF_H = 400;
@@ -38,43 +39,116 @@ export const FONT_FAMILY = 'Inter, sans-serif';
38
39
  * Uniform fit of the reference design into an element of size `w × h`: the
39
40
  * scale factor plus the centering offsets (letterboxed). Shared by the renderer
40
41
  * (to draw) and the view (to map clicks back into reference coords).
42
+ *
43
+ * The fit itself is the library's ({@link fitReference}, R37): only the
44
+ * reference size is this framework's business.
41
45
  */
42
46
  export function refScale(w, h) {
43
- const s = Math.min(w / REF_W, h / REF_H);
44
- return { s, ox: (w - REF_W * s) / 2, oy: (h - REF_H * s) / 2 };
47
+ return fitReference(w, h, REF_W, REF_H);
45
48
  }
46
49
  /**
47
- * Bounding box of the three circles in reference coords (small padding). The
48
- * REF margins around it only exist for the facet name labels — when a diagram
49
- * hides them (`cropToCircles`), the renderer fits THIS box into the element
50
- * bounds instead, so the background hugs the Venn.
50
+ * The three circles, and nothing else: their exact bounding box in reference
51
+ * coords. Both crop boxes below are this box plus what each of them has to make
52
+ * room for, so the two can never disagree about where the Venn is.
51
53
  */
52
- export const CROP = (() => {
53
- const pad = 8;
54
+ const CIRCLES = (() => {
54
55
  const ax = VENN.cx - 0.866 * VENN.r0; // Identity / Architecture centres
55
56
  const abY = VENN.cy - 0.5 * VENN.r0;
56
57
  const cY = VENN.cy + VENN.r0; // Experience centre
57
- const minX = ax - VENN.R - pad;
58
- const maxX = VENN.cx + 0.866 * VENN.r0 + VENN.R + pad;
59
- const minY = abY - VENN.R - pad;
60
- const maxY = cY + VENN.R + pad;
61
- return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
58
+ return {
59
+ minX: ax - VENN.R,
60
+ maxX: VENN.cx + 0.866 * VENN.r0 + VENN.R,
61
+ minY: abY - VENN.R,
62
+ maxY: cY + VENN.R,
63
+ };
62
64
  })();
63
65
  /**
64
- * Crop box KEEPING room for the three facet name labels (drawn outside the
65
- * circles): the circles box plus a fixed text allowance left/right and below.
66
- * Used when a cropped diagram still shows its labels.
66
+ * Bounding box of the three circles in reference coords, with just enough
67
+ * padding to see their outline. When a diagram hides its facet names
68
+ * (`cropToCircles` without `showLabels`) the renderer fits THIS box into the
69
+ * element bounds, so the background hugs the Venn.
70
+ *
71
+ * ## Why the padding is 2.5 and not the 8 it was
72
+ *
73
+ * The padding is the ONLY empty band such a board has, and it is spent at the
74
+ * element's scale, not at the reference one. The EDGY dynamic template draws
75
+ * its board at `DYN_SCALE = 4.8`, so eight reference units of padding were
76
+ * **32.4 model units** of nothing on each of the four sides — the board a user
77
+ * has to catch by its border (R37) sat a good inch away from the circles, which
78
+ * is what the recette of 23/09/2026 reported. 2.5 leaves 1.25 past the circles'
79
+ * own 2.5-wide outline, i.e. 6 model units at the dynamic board's scale and
80
+ * under 2 at a facets board's.
81
+ *
82
+ * `templates/dynamic.ts` places every element of the dynamic board in
83
+ * coordinates relative to this box (`dynToModel`) and sizes the board from it,
84
+ * so the template follows in the same breath: both are derived here, and a
85
+ * freshly inserted template is aligned by construction. A board built from the
86
+ * OLD template keeps its `xywh` and sees the Venn grow 3.8 % inside it — see
87
+ * the changeset.
67
88
  */
68
- export const CROP_LABELED = (() => {
69
- const sideAllowance = 140; // label offset (10) + text width headroom
70
- const bottomAllowance = 35; // experience label below the bottom circle
89
+ export const CROP = (() => {
90
+ const pad = 2.5;
71
91
  return {
72
- x: CROP.x - sideAllowance,
73
- y: CROP.y,
74
- w: CROP.w + 2 * sideAllowance,
75
- h: CROP.h + bottomAllowance,
92
+ x: CIRCLES.minX - pad,
93
+ y: CIRCLES.minY - pad,
94
+ w: CIRCLES.maxX - CIRCLES.minX + 2 * pad,
95
+ h: CIRCLES.maxY - CIRCLES.minY + 2 * pad,
76
96
  };
77
97
  })();
98
+ /**
99
+ * How far past the circles each side of the labelled box has to reach, in REF
100
+ * units. MEASURED on the canvas, in the shipped wording, at
101
+ * {@link LABEL_FONT_SIZE}; each number is that reach plus 4 or 5 units of
102
+ * gutter.
103
+ *
104
+ * It used to be one symmetric number — `sideAllowance = 140` either side of the
105
+ * padded box, `bottomAllowance = 35` under it — and the three words are not
106
+ * symmetric at all. "Identity" is written right-aligned 10 left of the left
107
+ * circle and reaches 63.6 past the circles; "Architecture" is written
108
+ * left-aligned 10 right of the right circle and reaches 98.1; "Experience"
109
+ * hangs 29.2 below the bottom one (a `middle` baseline plus the descender of
110
+ * its "p"); and above them there is no word at all, only the 1.25 of circle
111
+ * stroke. So a facets diagram was born inside 126.6 model units of nothing on
112
+ * its left and 74.8 on its right — and a framework background is caught by its
113
+ * border and by nothing else
114
+ * (`model/src/elements/framework-background/hit-test.ts`), which put the
115
+ * catchable edge a seventh of the board away from anything drawn.
116
+ *
117
+ * ## Why constants rather than a measurement at paint time
118
+ *
119
+ * Because the three names are EDITABLE props of the element (`identityLabel` &
120
+ * co) and `cropLabeledScale` is not only what the renderer draws through —
121
+ * `element-view.ts` maps every click back through it too. Deriving the box from
122
+ * the current text would rescale and re-centre the whole Venn on each
123
+ * keystroke, and move the click mapping under the user's finger while they
124
+ * type; two boards of the same size would also draw their circles at two
125
+ * different sizes. The allowance is furniture: it is measured once, here.
126
+ *
127
+ * A name rewritten to something much longer than the vocabulary therefore
128
+ * reaches past the element's edge. It paints (the surface clips nothing); only
129
+ * the SVG export, which crops to the `xywh`, would cut it.
130
+ */
131
+ const LABEL_ALLOWANCE = {
132
+ /** No word up there: the circle's own stroke, and room to see it. */
133
+ top: 5,
134
+ /** "Identity", right-aligned, reaching left of the circles. */
135
+ left: 68,
136
+ /** "Architecture", left-aligned, reaching right of them. */
137
+ right: 103,
138
+ /** "Experience", under the bottom circle, descender included. */
139
+ bottom: 32,
140
+ };
141
+ /**
142
+ * Crop box KEEPING room for the three facet name labels (drawn outside the
143
+ * circles): the circles plus {@link LABEL_ALLOWANCE}, which is asymmetric
144
+ * because the words are. Used when a cropped diagram still shows its labels.
145
+ */
146
+ export const CROP_LABELED = {
147
+ x: CIRCLES.minX - LABEL_ALLOWANCE.left,
148
+ y: CIRCLES.minY - LABEL_ALLOWANCE.top,
149
+ w: CIRCLES.maxX - CIRCLES.minX + LABEL_ALLOWANCE.left + LABEL_ALLOWANCE.right,
150
+ h: CIRCLES.maxY - CIRCLES.minY + LABEL_ALLOWANCE.top + LABEL_ALLOWANCE.bottom,
151
+ };
78
152
  function fitScale(box) {
79
153
  return (w, h) => {
80
154
  const s = Math.min(w / box.w, h / box.h);
@@ -111,7 +111,11 @@ const NAME = 'EDGY dynamic';
111
111
  export const edgyDynamicTemplate = {
112
112
  name: NAME,
113
113
  type: 'template',
114
- preview: `<svg width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"><circle cx="55" cy="34" r="18" fill="#00ea4e" opacity="0.9"/><circle cx="80" cy="34" r="18" fill="#034cee" opacity="0.9"/><circle cx="67" cy="54" r="18" fill="#ff0056" opacity="0.9"/><path d="M55 30 H80 M56 31 L66 52 M79 31 L69 52" stroke="#fff" stroke-width="2"/><rect x="51" y="26" width="8" height="8" fill="#fff"/><circle cx="80" cy="30" r="4" fill="#fff"/><path d="M62 49 h6 l3 3 -3 3 h-6 z" fill="#fff"/></svg>`,
114
+ // The thumbnail follows the board: the circles are drawn where the cropped
115
+ // {@link CROP} box puts them once it is fitted into the 135 × 80 tile
116
+ // (height-bound, `s = 80 / CROP.h`), so the tile shows the same framing the
117
+ // template actually inserts rather than a Venn floating in a tile of its own.
118
+ preview: `<svg width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"><circle cx="53.6" cy="28" r="27.2" fill="#00ea4e" opacity="0.9"/><circle cx="81.4" cy="28" r="27.2" fill="#034cee" opacity="0.9"/><circle cx="67.5" cy="52" r="27.2" fill="#ff0056" opacity="0.9"/><path d="M53.6 28 H81.4 M55.1 30.6 L66 49.4 M79.9 30.6 L69 49.4" stroke="#fff" stroke-width="3"/><rect x="48.6" y="23" width="10" height="10" fill="#fff"/><circle cx="81.4" cy="28" r="5" fill="#fff"/><path d="M63 48 h7 l4 4 -4 4 h-7 z" fill="#fff"/></svg>`,
115
119
  // Stamped by hand, and it is the one `commandId` in this pack that is a
116
120
  // literal rather than a derivation: importing the registry here would close
117
121
  // the very loop this module exists to avoid. The coverage test pairs the two
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-framework-edgy",
3
3
  "description": "Labre edgy framework for @formicoidea/labre-core.",
4
- "version": "0.42.0",
4
+ "version": "0.43.1",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "author": "lajola",
@@ -31,7 +31,7 @@
31
31
  "dist"
32
32
  ],
33
33
  "dependencies": {
34
- "@formicoidea/labre-core": "0.42.0",
34
+ "@formicoidea/labre-core": "0.43.1",
35
35
  "@preact/signals-core": "^1.8.0",
36
36
  "lit": "^3.2.0",
37
37
  "yjs": "^13.6.21"