@qe-libs/qeviz 0.2.0 → 0.5.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/README.md CHANGED
@@ -129,17 +129,21 @@ All three languages share the same chain operations:
129
129
  | `compare` | Second group to subtract (`group − compare`). Positive differences use the primary colour. |
130
130
  | `also` | Second group to overlay alongside `group`. |
131
131
  | `show` / `show=false` | Suppress all edges. |
132
+ | `color_scale` | Colour mapping (webENA ramps: saturation 0.25–1, opacity 0.3–1). `"model"` (default) rescales across the whole model, so plots of one model share a colour scale; `"plot"` rescales within the plot (webENA); `"absolute"` uses saturation = opacity = weight. |
133
+ | `edge_width` | Width of a weight-1 edge as a fraction of the plot width (default 0.04). Width is absolute — equal weights draw equally wide — and each node's diameter is the sum of its edges' widths. |
134
+ | `magnify` | Multiply this plot's widths and node sizes (not colour), e.g. for a faint subtraction. When set (even `1`), the plot is labelled "(scaled N.Nx)". |
132
135
 
133
136
  Label modes: `"on"`, `"off"`, `"click"`, `"auto"`.
134
137
 
135
138
  ### `qe_axes` / `.axes()` parameters
136
139
 
137
140
  Axes are **opt-in**: a plot draws the x/y axis cross only when `qe_axes()` is in the
138
- chain (or a `<qe-axes>` element is present). Each axis label is controlled independently:
141
+ chain (or a `<qe-axes>` element is present). Axis labels are opt-in too: `qe_axes()` alone
142
+ draws the lines with no labels. Each label is controlled independently:
139
143
 
140
144
  | Parameter | Description |
141
145
  |---|---|
142
- | `x` | `TRUE` labels the x-axis with its dimension name, a string sets custom text, `FALSE` omits the x-axis label. |
146
+ | `x` | `FALSE` (default) omits the x-axis label, `TRUE` labels it with its dimension name (e.g. `SVD1`), a string sets custom text. |
143
147
  | `y` | Same as `x`, for the y-axis. |
144
148
  | `show` / `show=false` | Suppress the axes entirely. |
145
149
 
@@ -149,7 +153,7 @@ qe_plot(set) |> qe_edges("FirstGame") |> qe_axes(x = "Task focus", y = TRUE)
149
153
 
150
154
  ## TypeScript / web component
151
155
 
152
- The `<qe-visual>` and `<qe-graph>` elements can be used directly in any HTML page. Layer configuration uses declarative child elements:
156
+ The `<qe-visual>` and `<qe-graph>` elements can be used directly in any HTML page. Mark sizes and colour follow webENA: `<qe-graph edge-width>` sets the width of a weight-1 edge (absolute, as a fraction of the plot width), `<qe-edges color-scale>` picks the colour rescaling (`model` / `plot` / `absolute`), and `<qe-edges magnify>` scales one plot and labels it. Layer configuration uses declarative child elements; each layer draws only when its element is present. Code-node positions always come from the model and set the plot extent, but the nodes are drawn only when `<qe-nodes>` is present. The R / Python / Julia wrappers emit `<qe-nodes>` alongside an edge network by default (`qe_nodes()` / `.nodes()` override that).
153
157
 
154
158
  ```html
155
159
  <script src="qeviz.umd.js"></script>
@@ -160,6 +164,7 @@ The `<qe-visual>` and `<qe-graph>` elements can be used directly in any HTML pag
160
164
  <qe-means confidence label="on"></qe-means>
161
165
  <qe-points label="auto"></qe-points>
162
166
  <qe-edges group="FirstGame" also="SecondGame"></qe-edges>
167
+ <qe-axes x y></qe-axes>
163
168
  </qe-graph>
164
169
  </qe-visual>
165
170
 
@@ -168,6 +173,46 @@ The `<qe-visual>` and `<qe-graph>` elements can be used directly in any HTML pag
168
173
  </script>
169
174
  ```
170
175
 
176
+ By default, all marks (nodes, mean markers, unit dots) size in graph-coordinate
177
+ units and scale with the data extent and wheel-zoom. Add `fixed-size` to
178
+ `<qe-points>` or `<qe-means>` to keep those markers a constant on-screen pixel
179
+ size instead — useful when embedding coordinated plots at different scales (the
180
+ webENA use case):
181
+
182
+ ```html
183
+ <qe-points fixed-size></qe-points>
184
+ <qe-means fixed-size></qe-means>
185
+ ```
186
+
187
+ In the language adapters this is `fixed_size = TRUE` on `qe_points()` / `qe_group()`
188
+ (R), `fixed_size=True` on `.points()` / `.group()` (Python), and
189
+ `fixed_size=true` on `qe_points` / `qe_group` (Julia).
190
+
191
+ #### Point scaling and centring
192
+
193
+ Unit points and means sit much closer to the origin than the code nodes, so
194
+ by default qeviz rescales them to fill the plot. Two `<qe-graph>` attributes
195
+ change how points are scaled and where the view is centred; both are optional
196
+ and unset by default:
197
+
198
+ | `<qe-graph>` attributes | Points are multiplied by |
199
+ |---|---|
200
+ | neither (default) | qeviz's fit: farthest node ÷ farthest point, so the outermost point meets the outermost node (the ENA Web Tool's default) |
201
+ | `scale-points="false"` | 1: raw coordinates, where each point sits at its network's centroid |
202
+ | `point-scale="N"` | N, overriding both, e.g. to match another tool's scaling |
203
+
204
+ `center="content"` centres the view on the middle of the nodes' and points'
205
+ bounding box instead of the origin (0, 0), so a network that sits off to one
206
+ side of the origin fills the plot; `range="network"` is then measured from that
207
+ centre. The default is the origin, the ENA convention.
208
+
209
+ ```html
210
+ <qe-graph scale-points="false" center="content"></qe-graph>
211
+ ```
212
+
213
+ In R these are `qe_plot(scale_points =, point_scale =, center =)`; the Python and
214
+ Julia adapters set them as `<qe-graph>` attributes for now.
215
+
171
216
  Child element presence controls layer visibility — add `<qe-points>` to show unit dots, omit it to hide them. A `MutationObserver` watches for child additions, removals, and attribute changes, so interactive controls can manipulate the DOM directly:
172
217
 
173
218
  ```js
@@ -177,6 +222,93 @@ edges.setAttribute("compare", "SecondGame");
177
222
  edges.removeAttribute("also");
178
223
  ```
179
224
 
225
+ ### Events
226
+
227
+ `<qe-graph>` dispatches interaction events on the public element with
228
+ `bubbles: true, composed: true`, so a host app can subscribe regardless of shadow
229
+ DOM. Each event's `detail` also carries the `originalEvent`.
230
+
231
+ | Event | `detail` |
232
+ |---|---|
233
+ | `qe-edge-click` / `qe-edge-hover` / `qe-edge-unhover` | `{ source, target, weight, directed, self, group?, unit? }` |
234
+ | `qe-node-click` / `qe-node-hover` / `qe-node-unhover` | `{ id, kind: "node" \| "mean" \| "point", name, x, y, group?, unit? }` |
235
+ | `qe-label-move` | `{ id, transform: { x, y } }` — a label was dragged (offset in graph-space units) |
236
+
237
+ Labels are **draggable** (drag to reposition; the label pins open and stays
238
+ visible), emitting `qe-label-move` on drop so the host can persist the position
239
+ or mirror it across coordinated plots.
240
+
241
+ For a quick built-in tooltip on hover — `source – target (weight)` over edges,
242
+ the mark name over nodes — add the `tooltip` attribute to `<qe-graph>`. It is
243
+ opt-in; most hosts render their own from the hover events instead.
244
+
245
+ ```html
246
+ <qe-graph tooltip>…</qe-graph>
247
+ ```
248
+
249
+ `source`/`target` are code-node names; `x`/`y` are graph-space coordinates. Unhover
250
+ events carry `{ key }` identifying the mark/edge that was left. The host reacts and
251
+ pushes state back declaratively (ModelData + layer attributes) — qeviz adds no
252
+ framework coupling.
253
+
254
+ ```js
255
+ graph.addEventListener("qe-edge-click", (e) => {
256
+ const { source, target, weight } = e.detail; // e.g. open a conversation view
257
+ });
258
+ graph.addEventListener("qe-node-click", (e) => {
259
+ if (e.detail.kind === "point") plotUnit(e.detail.id);
260
+ });
261
+ ```
262
+
263
+ ### Instance access & read APIs
264
+
265
+ Give coordinated plots an identity and look them up, and read the resolved model
266
+ for host-side hit-testing or export:
267
+
268
+ ```js
269
+ import { getGraph, getGraphs } from "@qe-libs/qeviz";
270
+
271
+ getGraph("comparison"); // by id or plot-group attribute
272
+ getGraphs(); // all connected <qe-graph> instances
273
+
274
+ const graph = getGraph("comparison");
275
+ graph.getNodes(); // [{ id, name, x, y }, …]
276
+ graph.getEdges(); // [{ source, target, weight, directed, self }, …]
277
+ graph.getPoints(); // [{ id, group, x, y }, …] (unit points)
278
+ graph.pointsInRect({ x, y, w, h }); // ids of unit points in a graph-space rect
279
+ ```
280
+
281
+ ### Transitions & export
282
+
283
+ Opt into animated transitions with the `animate` attribute — on the next
284
+ `setModelData`, marks glide from their old positions to the new ones instead of
285
+ snapping (default 300 ms; `animate="500"` sets the duration):
286
+
287
+ ```html
288
+ <qe-graph animate>…</qe-graph>
289
+ ```
290
+
291
+ Snapshot the current plot for download or embedding:
292
+
293
+ ```js
294
+ graph.toSVG(); // standalone SVG string
295
+ await graph.toPNG(2); // PNG data URL (2× resolution)
296
+ ```
297
+
298
+ ### Selection / highlight
299
+
300
+ Drive selection styling from the host without touching qeviz's internal DOM. The
301
+ highlight is an overlay that survives model updates:
302
+
303
+ ```js
304
+ graph.setHighlight({ edges: [{ source: "Data", target: "Design" }], nodes: ["Data"] });
305
+ graph.clearHighlight();
306
+ ```
307
+
308
+ ```html
309
+ <qe-graph id="primary" plot-group="comparison" …></qe-graph>
310
+ ```
311
+
180
312
  ### Build
181
313
 
182
314
  ```sh