@data-profile/fingerprint 0.0.0-stage → 0.2.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.
@@ -0,0 +1,632 @@
1
+ import {
2
+ CALLOUT_GUTTER,
3
+ CALLOUT_HEIGHT,
4
+ FingerprintDataError,
5
+ describeLayout,
6
+ emptyLayout,
7
+ formFromItems,
8
+ layoutFingerprint,
9
+ markOpacity,
10
+ placeCallouts,
11
+ ridgeOpacity
12
+ } from "../chunk-eygy4k4w.js";
13
+
14
+ // temp/src/react/FingerprintCanvas.tsx
15
+ import {
16
+ memo,
17
+ useCallback,
18
+ useEffect,
19
+ useId,
20
+ useMemo,
21
+ useRef,
22
+ useState
23
+ } from "react";
24
+
25
+ // temp/src/react/renderers.tsx
26
+ import { jsx } from "react/jsx-runtime";
27
+ var shapesRenderer = {
28
+ name: "shapes",
29
+ mark: ({ node }) => {
30
+ const r = node.size / 2;
31
+ const paint = {
32
+ fill: node.color,
33
+ fillOpacity: markOpacity(node)
34
+ };
35
+ if (node.shape === null)
36
+ return /* @__PURE__ */ jsx("circle", {
37
+ r: r * 0.8,
38
+ fill: "none",
39
+ stroke: node.color,
40
+ strokeOpacity: markOpacity(node),
41
+ strokeWidth: r * 0.35
42
+ });
43
+ switch (node.shape % 5) {
44
+ case 1:
45
+ return /* @__PURE__ */ jsx("rect", {
46
+ x: -r * 0.85,
47
+ y: -r * 0.85,
48
+ width: r * 1.7,
49
+ height: r * 1.7,
50
+ rx: r * 0.25,
51
+ ...paint
52
+ });
53
+ case 2:
54
+ return /* @__PURE__ */ jsx("polygon", {
55
+ points: `0,${-r} ${r * 0.95},${r * 0.75} ${-r * 0.95},${r * 0.75}`,
56
+ ...paint
57
+ });
58
+ case 3:
59
+ return /* @__PURE__ */ jsx("polygon", {
60
+ points: `0,${-r} ${r},0 0,${r} ${-r},0`,
61
+ ...paint
62
+ });
63
+ case 4:
64
+ return /* @__PURE__ */ jsx("polygon", {
65
+ points: Array.from({ length: 6 }, (_, i) => {
66
+ const a = Math.PI / 3 * i;
67
+ return `${(r * Math.cos(a)).toFixed(2)},${(r * Math.sin(a)).toFixed(2)}`;
68
+ }).join(" "),
69
+ ...paint
70
+ });
71
+ default:
72
+ return /* @__PURE__ */ jsx("circle", {
73
+ r,
74
+ ...paint
75
+ });
76
+ }
77
+ }
78
+ };
79
+ var dotsRenderer = {
80
+ name: "dots",
81
+ mark: ({ node }) => node.shape === null ? /* @__PURE__ */ jsx("circle", {
82
+ r: node.size * 0.4,
83
+ fill: "none",
84
+ stroke: node.color,
85
+ strokeOpacity: markOpacity(node),
86
+ strokeWidth: node.size * 0.18
87
+ }) : /* @__PURE__ */ jsx("circle", {
88
+ r: node.size / 2,
89
+ fill: node.color,
90
+ fillOpacity: markOpacity(node)
91
+ })
92
+ };
93
+
94
+ // temp/src/react/FingerprintCanvas.tsx
95
+ import { jsx as jsx2, jsxs, Fragment } from "react/jsx-runtime";
96
+ var halfTurn = (degrees) => ((degrees + 90) % 180 + 180) % 180 - 90;
97
+ var cssString = (value) => `"${value.replace(/["\\]/g, "\\$&").replace(/\n/g, "\\a ")}"`;
98
+ function useCarriedMarks(layout) {
99
+ const committed = useRef({ keyOf: new Map, order: [] });
100
+ const pending = useRef(committed.current);
101
+ const marks = useMemo(() => {
102
+ const previous = committed.current;
103
+ const keyOf = new Map;
104
+ const nodeOf = new Map;
105
+ layout.nodes.forEach((node, i) => {
106
+ let key;
107
+ for (const id of node.itemIds) {
108
+ const candidate = previous.keyOf.get(id);
109
+ if (candidate !== undefined && !nodeOf.has(candidate)) {
110
+ key = candidate;
111
+ break;
112
+ }
113
+ }
114
+ if (key === undefined)
115
+ key = nodeOf.has(node.id) ? `${node.id}~${i}` : node.id;
116
+ nodeOf.set(key, node);
117
+ for (const id of node.itemIds)
118
+ keyOf.set(id, key);
119
+ });
120
+ const kept = previous.order.filter((key) => nodeOf.has(key));
121
+ const keptSet = new Set(kept);
122
+ const order = [...kept, ...[...nodeOf.keys()].filter((key) => !keptSet.has(key))];
123
+ pending.current = { keyOf, order };
124
+ return order.map((key) => ({ key, node: nodeOf.get(key) }));
125
+ }, [layout]);
126
+ useEffect(() => {
127
+ committed.current = pending.current;
128
+ }, [marks]);
129
+ return marks;
130
+ }
131
+ var DIMMED = 0.22;
132
+ var Mark = memo(function Mark2({
133
+ node,
134
+ dimensions,
135
+ arrange,
136
+ renderer,
137
+ idPrefix,
138
+ onChoose
139
+ }) {
140
+ const attributes = {};
141
+ dimensions.forEach((id, k) => attributes[`data-d${k}`] = node.categories[id] ?? "");
142
+ return /* @__PURE__ */ jsx2("g", {
143
+ className: "fp-mark",
144
+ "data-category": node.categories[arrange],
145
+ ...attributes,
146
+ onClick: onChoose ? () => onChoose(node.categories[arrange]) : undefined,
147
+ style: {
148
+ transform: `translate(${node.x}px, ${node.y}px) rotate(${halfTurn(node.rotation)}deg)`
149
+ },
150
+ children: renderer.mark({ node, idPrefix })
151
+ });
152
+ });
153
+ function useWidth() {
154
+ const ref = useRef(null);
155
+ const [width, setWidth] = useState(null);
156
+ useEffect(() => {
157
+ const element = ref.current;
158
+ if (!element || typeof ResizeObserver !== "function")
159
+ return;
160
+ const observer = new ResizeObserver(([entry]) => setWidth(entry?.contentRect.width ?? null));
161
+ observer.observe(element);
162
+ return () => observer.disconnect();
163
+ }, []);
164
+ return [ref, width];
165
+ }
166
+ var visuallyHidden = {
167
+ position: "absolute",
168
+ width: 1,
169
+ height: 1,
170
+ overflow: "hidden",
171
+ clip: "rect(0 0 0 0)",
172
+ whiteSpace: "nowrap"
173
+ };
174
+ function FingerprintCanvas({
175
+ layout,
176
+ title,
177
+ description,
178
+ renderer = shapesRenderer,
179
+ ridges,
180
+ selected = null,
181
+ onSelect,
182
+ annotations = [],
183
+ callouts,
184
+ unit = "items",
185
+ motion,
186
+ className
187
+ }) {
188
+ const uid = useId().replace(/[^\w-]/g, "");
189
+ const [ref, width] = useWidth();
190
+ const placed = useMemo(() => placeCallouts(layout, annotations), [layout, annotations]);
191
+ const mode = placed.length === 0 ? "none" : (callouts?.placement ?? "auto") === "auto" ? width !== null && width < (callouts?.breakpoint ?? 640) ? "below" : "beside" : callouts.placement;
192
+ const gutter = mode === "beside" ? CALLOUT_GUTTER : 0;
193
+ const opacity = ridgeOpacity(layout.itemCount, ridges);
194
+ const selectedEntry = selected ? layout.legends.find((group) => group.dimensionId === selected.dimensionId)?.entries.find((entry) => entry.id === selected.categoryId) : undefined;
195
+ const latest = useRef({ selected, onSelect, dimensionId: layout.encoding.arrange });
196
+ latest.current = { selected, onSelect, dimensionId: layout.encoding.arrange };
197
+ const choose = useCallback((categoryId) => {
198
+ const { selected: current, onSelect: select, dimensionId } = latest.current;
199
+ select?.(current?.dimensionId === dimensionId && current.categoryId === categoryId ? null : { dimensionId, categoryId });
200
+ }, []);
201
+ const dimensions = useMemo(() => layout.legends.map((g) => g.dimensionId), [layout.legends]);
202
+ const marks = useCarriedMarks(layout);
203
+ const scope = `.fp-${uid} .fp-mark`;
204
+ const selectedIndex = selected ? dimensions.indexOf(selected.dimensionId) : -1;
205
+ const glides = layout.nodes.length <= (motion?.glide ?? 800);
206
+ const fades = layout.nodes.length <= (motion?.fade ?? 400);
207
+ const css = [
208
+ `${scope}{transition:${glides ? "transform 700ms cubic-bezier(.2,.7,.2,1)," : ""}opacity 250ms ease${onSelect ? ";cursor:pointer" : ""}}`,
209
+ fades ? `${scope}>*{transition:fill 600ms ease,fill-opacity 600ms ease,stroke 600ms ease}` : "",
210
+ `@media (prefers-reduced-motion:reduce){${scope},${scope}>*{transition:none}}`,
211
+ selected && selectedIndex >= 0 ? `${scope}:not([data-d${selectedIndex}=${cssString(selected.categoryId)}]){opacity:${DIMMED}}` : ""
212
+ ].join(`
213
+ `);
214
+ const ridgeLines = useMemo(() => opacity > 0 ? /* @__PURE__ */ jsx2("g", {
215
+ className: "fp-ridges",
216
+ fill: "none",
217
+ stroke: ridges?.color ?? "currentColor",
218
+ strokeOpacity: opacity,
219
+ strokeWidth: layout.ridgeSpacing * (ridges?.width ?? 0.12),
220
+ strokeLinecap: "round",
221
+ strokeLinejoin: "round",
222
+ children: layout.ridges.map((ridge, i) => /* @__PURE__ */ jsx2("polyline", {
223
+ points: ridge.map(([x, y]) => `${x.toFixed(1)},${y.toFixed(1)}`).join(" ")
224
+ }, i))
225
+ }) : null, [opacity, ridges?.color, ridges?.width, layout.ridgeSpacing, layout.ridges]);
226
+ return /* @__PURE__ */ jsxs("div", {
227
+ ref,
228
+ className: ["fp-canvas", `fp-${uid}`, className].filter(Boolean).join(" "),
229
+ style: { position: "relative" },
230
+ "data-selection": selected ? `${selected.dimensionId}:${selected.categoryId}` : undefined,
231
+ children: [
232
+ /* @__PURE__ */ jsx2("style", {
233
+ children: css
234
+ }),
235
+ /* @__PURE__ */ jsxs("svg", {
236
+ viewBox: `${-gutter} 0 ${layout.width + gutter * 2} ${layout.height}`,
237
+ role: "img",
238
+ "aria-labelledby": `${uid}-title ${uid}-desc`,
239
+ style: { display: "block", width: "100%", height: "auto", overflow: "visible" },
240
+ children: [
241
+ /* @__PURE__ */ jsx2("title", {
242
+ id: `${uid}-title`,
243
+ children: title
244
+ }),
245
+ /* @__PURE__ */ jsx2("desc", {
246
+ id: `${uid}-desc`,
247
+ children: description
248
+ }),
249
+ renderer.defs && /* @__PURE__ */ jsx2("defs", {
250
+ children: renderer.defs({ idPrefix: uid, legends: layout.legends })
251
+ }),
252
+ ridgeLines,
253
+ /* @__PURE__ */ jsx2("g", {
254
+ className: "fp-marks",
255
+ children: marks.map(({ key, node }) => /* @__PURE__ */ jsx2(Mark, {
256
+ node,
257
+ dimensions,
258
+ arrange: layout.encoding.arrange,
259
+ renderer,
260
+ idPrefix: uid,
261
+ onChoose: onSelect ? choose : undefined
262
+ }, key))
263
+ }),
264
+ mode === "beside" && placed.map((callout) => {
265
+ const left = callout.side === "left";
266
+ const edge = left ? -12 : layout.width + 12;
267
+ return /* @__PURE__ */ jsxs("g", {
268
+ className: "fp-callout",
269
+ "data-side": callout.side,
270
+ children: [
271
+ /* @__PURE__ */ jsx2("polyline", {
272
+ className: "fp-callout__leader",
273
+ points: `${edge},${callout.labelY + 14} ${left ? edge + 10 : edge - 10},${callout.labelY + 14} ${callout.anchor.x},${callout.anchor.y}`,
274
+ fill: "none",
275
+ stroke: "currentColor",
276
+ strokeWidth: 1.2
277
+ }),
278
+ /* @__PURE__ */ jsx2("circle", {
279
+ cx: callout.anchor.x,
280
+ cy: callout.anchor.y,
281
+ r: 3.5,
282
+ fill: "currentColor"
283
+ }),
284
+ /* @__PURE__ */ jsx2("foreignObject", {
285
+ x: left ? -gutter : layout.width + 16,
286
+ y: callout.labelY,
287
+ width: gutter - 16,
288
+ height: CALLOUT_HEIGHT,
289
+ children: /* @__PURE__ */ jsxs("div", {
290
+ className: "fp-callout__label",
291
+ style: { textAlign: left ? "right" : "left", fontSize: 13, lineHeight: 1.35 },
292
+ children: [
293
+ /* @__PURE__ */ jsx2("strong", {
294
+ style: { display: "block", fontSize: 15 },
295
+ children: callout.annotation.title
296
+ }),
297
+ callout.annotation.body && /* @__PURE__ */ jsx2("span", {
298
+ children: callout.annotation.body
299
+ })
300
+ ]
301
+ })
302
+ })
303
+ ]
304
+ }, callout.annotation.id);
305
+ }),
306
+ mode === "below" && placed.map((callout) => /* @__PURE__ */ jsxs("g", {
307
+ className: "fp-callout-marker",
308
+ "aria-hidden": "true",
309
+ children: [
310
+ /* @__PURE__ */ jsx2("circle", {
311
+ cx: callout.anchor.x,
312
+ cy: callout.anchor.y,
313
+ r: 11,
314
+ fill: "currentColor"
315
+ }),
316
+ /* @__PURE__ */ jsx2("text", {
317
+ x: callout.anchor.x,
318
+ y: callout.anchor.y,
319
+ dy: "0.35em",
320
+ textAnchor: "middle",
321
+ fontSize: 13,
322
+ fontWeight: 700,
323
+ style: { fill: "var(--fp-callout-ink, Canvas)" },
324
+ children: callout.number
325
+ })
326
+ ]
327
+ }, callout.annotation.id))
328
+ ]
329
+ }),
330
+ mode === "below" && /* @__PURE__ */ jsx2("ol", {
331
+ className: "fp-callouts",
332
+ children: placed.map((callout) => /* @__PURE__ */ jsxs("li", {
333
+ value: callout.number,
334
+ children: [
335
+ /* @__PURE__ */ jsx2("strong", {
336
+ children: callout.annotation.title
337
+ }),
338
+ callout.annotation.body && /* @__PURE__ */ jsxs(Fragment, {
339
+ children: [
340
+ " ",
341
+ callout.annotation.body
342
+ ]
343
+ })
344
+ ]
345
+ }, callout.annotation.id))
346
+ }),
347
+ mode === "beside" && /* @__PURE__ */ jsx2("ul", {
348
+ style: visuallyHidden,
349
+ children: placed.map((callout) => /* @__PURE__ */ jsxs("li", {
350
+ children: [
351
+ callout.annotation.title,
352
+ ". ",
353
+ callout.annotation.body
354
+ ]
355
+ }, callout.annotation.id))
356
+ }),
357
+ /* @__PURE__ */ jsx2("p", {
358
+ role: "status",
359
+ "aria-live": "polite",
360
+ style: visuallyHidden,
361
+ children: selectedEntry ? `${selectedEntry.label}: ${selectedEntry.count.toLocaleString("en-GB")} ${unit}.` : ""
362
+ })
363
+ ]
364
+ });
365
+ }
366
+ // temp/src/react/FingerprintControls.tsx
367
+ import { useId as useId2 } from "react";
368
+ import { jsx as jsx3, jsxs as jsxs2, Fragment as Fragment2 } from "react/jsx-runtime";
369
+ var join = (...names) => names.filter(Boolean).join(" ");
370
+ function FingerprintViewSwitch({
371
+ views,
372
+ value,
373
+ onChange,
374
+ label = "View",
375
+ className
376
+ }) {
377
+ return /* @__PURE__ */ jsx3("div", {
378
+ role: "group",
379
+ "aria-label": label,
380
+ className: join("fp-views", className),
381
+ children: views.map((view) => /* @__PURE__ */ jsx3("button", {
382
+ type: "button",
383
+ className: "fp-views__view",
384
+ "aria-pressed": view.id === value,
385
+ onClick: () => onChange(view.id),
386
+ children: view.label
387
+ }, view.id))
388
+ });
389
+ }
390
+ var isSelected = (selected, group, id) => selected?.dimensionId === group.dimensionId && selected.categoryId === id;
391
+ function FingerprintLegend({
392
+ group,
393
+ renderer = shapesRenderer,
394
+ selected = null,
395
+ onSelect,
396
+ heading = true,
397
+ counts = true,
398
+ hideEmpty = false,
399
+ className
400
+ }) {
401
+ const uid = useId2().replace(/[^\w-]/g, "");
402
+ const headingId = `${uid}-heading`;
403
+ return /* @__PURE__ */ jsxs2("div", {
404
+ className: join("fp-legend", className),
405
+ "data-channels": group.channels.join(" "),
406
+ children: [
407
+ heading && /* @__PURE__ */ jsx3("p", {
408
+ id: headingId,
409
+ className: "fp-legend__heading",
410
+ children: group.label
411
+ }),
412
+ /* @__PURE__ */ jsx3("ul", {
413
+ "aria-labelledby": heading ? headingId : undefined,
414
+ "aria-label": heading ? undefined : group.label,
415
+ style: { listStyle: "none", padding: 0, margin: 0 },
416
+ children: group.entries.filter((entry) => !hideEmpty || entry.count > 0).map((entry, index) => {
417
+ const prefix = `${uid}-${index}`;
418
+ const swatch = /* @__PURE__ */ jsxs2("svg", {
419
+ viewBox: "-7 -7 14 14",
420
+ width: "1em",
421
+ height: "1em",
422
+ "aria-hidden": "true",
423
+ className: "fp-legend__swatch",
424
+ children: [
425
+ renderer.defs && /* @__PURE__ */ jsx3("defs", {
426
+ children: renderer.defs({ idPrefix: prefix, legends: [group] })
427
+ }),
428
+ renderer.mark({
429
+ node: {
430
+ id: entry.id,
431
+ itemIds: [],
432
+ categories: { [group.dimensionId]: entry.id },
433
+ x: 0,
434
+ y: 0,
435
+ rotation: 0,
436
+ size: 12,
437
+ weight: 1,
438
+ color: entry.color,
439
+ shape: entry.shape,
440
+ lightness: entry.lightness
441
+ },
442
+ idPrefix: prefix
443
+ })
444
+ ]
445
+ });
446
+ const text = /* @__PURE__ */ jsxs2(Fragment2, {
447
+ children: [
448
+ swatch,
449
+ /* @__PURE__ */ jsx3("span", {
450
+ className: "fp-legend__label",
451
+ children: entry.label
452
+ }),
453
+ counts && /* @__PURE__ */ jsx3("span", {
454
+ className: "fp-legend__count",
455
+ children: entry.count.toLocaleString("en-GB")
456
+ })
457
+ ]
458
+ });
459
+ return /* @__PURE__ */ jsx3("li", {
460
+ className: "fp-legend__entry",
461
+ children: onSelect ? /* @__PURE__ */ jsx3("button", {
462
+ type: "button",
463
+ className: "fp-legend__toggle",
464
+ "aria-pressed": isSelected(selected, group, entry.id),
465
+ onClick: () => onSelect(isSelected(selected, group, entry.id) ? null : { dimensionId: group.dimensionId, categoryId: entry.id }),
466
+ children: text
467
+ }) : text
468
+ }, entry.id);
469
+ })
470
+ })
471
+ ]
472
+ });
473
+ }
474
+ function FingerprintList({
475
+ group,
476
+ unit = "items",
477
+ linkLabel = "Explore",
478
+ selected = null,
479
+ onSelect,
480
+ className
481
+ }) {
482
+ const total = group.entries.reduce((sum, entry) => sum + entry.count, 0);
483
+ const share = (count) => total ? `${Math.round(count / total * 100)}%` : "–";
484
+ const links = group.entries.some((entry) => entry.href);
485
+ return /* @__PURE__ */ jsxs2("table", {
486
+ className: join("fp-list", className),
487
+ children: [
488
+ /* @__PURE__ */ jsxs2("caption", {
489
+ children: [
490
+ group.label,
491
+ ": ",
492
+ total.toLocaleString("en-GB"),
493
+ " ",
494
+ unit
495
+ ]
496
+ }),
497
+ /* @__PURE__ */ jsx3("thead", {
498
+ children: /* @__PURE__ */ jsxs2("tr", {
499
+ children: [
500
+ /* @__PURE__ */ jsx3("th", {
501
+ scope: "col",
502
+ children: group.label
503
+ }),
504
+ /* @__PURE__ */ jsx3("th", {
505
+ scope: "col",
506
+ children: unit[0].toUpperCase() + unit.slice(1)
507
+ }),
508
+ /* @__PURE__ */ jsx3("th", {
509
+ scope: "col",
510
+ children: "Share"
511
+ }),
512
+ links && /* @__PURE__ */ jsx3("th", {
513
+ scope: "col",
514
+ children: /* @__PURE__ */ jsx3("span", {
515
+ className: "fp-list__hidden",
516
+ children: "Link"
517
+ })
518
+ })
519
+ ]
520
+ })
521
+ }),
522
+ /* @__PURE__ */ jsx3("tbody", {
523
+ children: group.entries.map((entry) => /* @__PURE__ */ jsxs2("tr", {
524
+ "data-selected": isSelected(selected, group, entry.id) || undefined,
525
+ children: [
526
+ /* @__PURE__ */ jsx3("th", {
527
+ scope: "row",
528
+ children: onSelect ? /* @__PURE__ */ jsx3("button", {
529
+ type: "button",
530
+ className: "fp-list__toggle",
531
+ "aria-pressed": isSelected(selected, group, entry.id),
532
+ onClick: () => onSelect(isSelected(selected, group, entry.id) ? null : { dimensionId: group.dimensionId, categoryId: entry.id }),
533
+ children: entry.label
534
+ }) : entry.label
535
+ }),
536
+ /* @__PURE__ */ jsx3("td", {
537
+ children: entry.count.toLocaleString("en-GB")
538
+ }),
539
+ /* @__PURE__ */ jsx3("td", {
540
+ children: share(entry.count)
541
+ }),
542
+ links && /* @__PURE__ */ jsx3("td", {
543
+ children: entry.href && /* @__PURE__ */ jsxs2("a", {
544
+ href: entry.href,
545
+ children: [
546
+ linkLabel,
547
+ /* @__PURE__ */ jsxs2("span", {
548
+ className: "fp-list__hidden",
549
+ children: [
550
+ " ",
551
+ entry.label
552
+ ]
553
+ })
554
+ ]
555
+ })
556
+ })
557
+ ]
558
+ }, entry.id))
559
+ })
560
+ ]
561
+ });
562
+ }
563
+ // temp/src/react/useFingerprint.ts
564
+ import { useCallback as useCallback2, useMemo as useMemo2, useState as useState2 } from "react";
565
+ function useFingerprint({
566
+ items,
567
+ dimensions,
568
+ views: given,
569
+ initialViewId,
570
+ form,
571
+ seed = "fingerprint",
572
+ maxMarks,
573
+ unit = "items"
574
+ }) {
575
+ const views = useMemo2(() => given ?? dimensions.map((d) => ({ id: d.id, label: d.label, encoding: { arrange: d.id } })), [given, dimensions]);
576
+ const [viewId, setView] = useState2(initialViewId ?? views[0]?.id ?? "");
577
+ const [selected, setSelected] = useState2(null);
578
+ const view = views.find((v) => v.id === viewId) ?? views[0];
579
+ const resolvedForm = useMemo2(() => ({ ...formFromItems(items, dimensions, seed), ...form }), [items, dimensions, seed, form]);
580
+ const { layout, error } = useMemo2(() => {
581
+ try {
582
+ const layout2 = layoutFingerprint({
583
+ items,
584
+ dimensions,
585
+ encoding: view?.encoding,
586
+ seed,
587
+ form: resolvedForm,
588
+ maxMarks
589
+ });
590
+ return { layout: layout2, error: null };
591
+ } catch (caught) {
592
+ if (caught instanceof FingerprintDataError)
593
+ return { layout: emptyLayout(), error: caught };
594
+ throw caught;
595
+ }
596
+ }, [items, dimensions, view, seed, resolvedForm, maxMarks]);
597
+ const description = useMemo2(() => error ? error.message : describeLayout(layout, unit), [layout, error, unit]);
598
+ const setViewId = useCallback2((id) => {
599
+ setView(id);
600
+ setSelected(null);
601
+ }, []);
602
+ const canvasProps = useMemo2(() => ({ layout, description, selected, onSelect: setSelected, unit }), [layout, description, selected, unit]);
603
+ const legendProps = useCallback2((group) => ({ group, selected, onSelect: setSelected }), [selected]);
604
+ const listProps = useCallback2((group) => ({ group, selected, onSelect: setSelected, unit }), [selected, unit]);
605
+ return {
606
+ layout,
607
+ description,
608
+ error,
609
+ views,
610
+ view,
611
+ viewId: view?.id ?? "",
612
+ setViewId,
613
+ selected,
614
+ setSelected,
615
+ canvasProps,
616
+ legendProps,
617
+ listProps
618
+ };
619
+ }
620
+ export {
621
+ useFingerprint,
622
+ shapesRenderer,
623
+ markOpacity,
624
+ dotsRenderer,
625
+ FingerprintViewSwitch,
626
+ FingerprintList,
627
+ FingerprintLegend,
628
+ FingerprintCanvas
629
+ };
630
+
631
+ //# debugId=F7CD85AE8DCB22DE64756E2164756E21
632
+ //# sourceMappingURL=index.js.map