@spotlab/hand-matrix 0.4.0 → 0.5.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.
- package/README.md +40 -38
- package/dist/editor/matrix-editor.d.ts +5 -12
- package/dist/hand-matrix.d.ts +26 -12
- package/dist/index.d.ts +2 -2
- package/dist/index.js +272 -268
- package/dist/range-matrix.d.ts +10 -0
- package/dist/range-to-matrix.d.ts +19 -0
- package/package.json +1 -1
- package/dist/range-grid.d.ts +0 -13
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@ and [`@spotlab/range`](../range) — no Tailwind, no bundler-plugin
|
|
|
5
5
|
requirement.
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
|
-
import {
|
|
8
|
+
import { RangeMatrix, rangeToMatrix } from "@spotlab/hand-matrix";
|
|
9
9
|
import "@spotlab/hand-matrix/style.css";
|
|
10
10
|
import { initRange } from "@spotlab/range";
|
|
11
11
|
|
|
12
12
|
await initRange(); // once, at startup
|
|
13
13
|
|
|
14
|
-
<
|
|
14
|
+
<RangeMatrix {...rangeToMatrix("AKs:0.5,QQ")} />;
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Exports
|
|
@@ -20,31 +20,33 @@ Everything below is exported from the package root.
|
|
|
20
20
|
|
|
21
21
|
### Display
|
|
22
22
|
|
|
23
|
-
- `
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- `className?: string
|
|
37
|
-
- `
|
|
38
|
-
`
|
|
39
|
-
|
|
40
|
-
`
|
|
41
|
-
to `
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
23
|
+
- `RangeMatrix` — the read-only grid, for one range or several actions at
|
|
24
|
+
once, drawn exactly as `RangeMatrixEditor` draws it but without painting.
|
|
25
|
+
Each cell stacks its actions' weights as colored bands, dead cells
|
|
26
|
+
(`avail` 0) are hatched, and capped cells (`avail` below 1) show a cap
|
|
27
|
+
line with the rest hatched. Each cell carries a `data-combo` attribute.
|
|
28
|
+
Props (`RangeMatrixProps`):
|
|
29
|
+
- `cells: EditorCell[]` — one per combo, in `@spotlab/range`'s `COMBOS`
|
|
30
|
+
order (see [Editing](#editing)).
|
|
31
|
+
- `actions: EditorActionSpec[]` — index-aligned with each cell's
|
|
32
|
+
`weights`.
|
|
33
|
+
- `order: number[]` — indices into `actions`, in the order bands stack.
|
|
34
|
+
An action left out isn't drawn, so its share of a cell stays
|
|
35
|
+
transparent; include it to give it a color.
|
|
36
|
+
- `className?: string`.
|
|
37
|
+
- `rangeToMatrix(range, { color?, labels? }): RangeMatrixProps` (without
|
|
38
|
+
`className`) — `RangeMatrix`'s props for drawing one range:
|
|
39
|
+
`<RangeMatrix {...rangeToMatrix(range)} />`. Takes a range string (parsed
|
|
40
|
+
via `@spotlab/range`) or the expanded `HandFrequency[]` form, and fills
|
|
41
|
+
each cell to its combo's mean weight in `color` (default
|
|
42
|
+
`var(--spotlab-hm-fill)`), leaving the rest blank. The returned `actions`
|
|
43
|
+
are `in` and `out`, labeled by `labels.in` (default `"In range"`) and
|
|
44
|
+
`labels.out` (default `"Out of range"`), for building your own legend.
|
|
45
|
+
Memoize the result (e.g. `useMemo`) rather than calling it on every
|
|
46
|
+
render.
|
|
47
|
+
|
|
48
|
+
`rangeToMatrix`'s parse and combo collapse (`toComboWeights`) are wasm
|
|
49
|
+
calls, so `initRange()` must have resolved before calling it — see
|
|
48
50
|
[`@spotlab/range`](../range)'s own README for why that call is explicit
|
|
49
51
|
rather than automatic.
|
|
50
52
|
|
|
@@ -55,9 +57,8 @@ raise). Its state is an array of 169 `EditorCell`s, one per combo in
|
|
|
55
57
|
`@spotlab/range`'s `COMBOS` order. Every component is fully controlled: state
|
|
56
58
|
goes in as props and changes come out through `on*Change` callbacks.
|
|
57
59
|
|
|
58
|
-
- `RangeMatrixEditor` — the paintable grid
|
|
59
|
-
|
|
60
|
-
wires brush/eyedropper painting onto `HandMatrix` for mouse and touch.
|
|
60
|
+
- `RangeMatrixEditor` — the paintable grid: `RangeMatrix`'s cells with
|
|
61
|
+
brush/eyedropper painting wired on for mouse and touch.
|
|
61
62
|
Props (`RangeMatrixEditorProps`):
|
|
62
63
|
- `cells: EditorCell[]` and `onCellsChange(cells)`.
|
|
63
64
|
- `actions: EditorActionSpec[]` — index-aligned with each cell's
|
|
@@ -85,9 +86,9 @@ goes in as props and changes come out through `on*Change` callbacks.
|
|
|
85
86
|
- `useRangePainting(opts)` — the brush/eyedropper state machine behind
|
|
86
87
|
`RangeMatrixEditor`, for building your own grid. `opts` takes the editor's
|
|
87
88
|
`cells`, `brush`, `tool` and their three `on*Change` callbacks. Returns
|
|
88
|
-
`{ onCellDown(combo), onCellEnter(combo) }
|
|
89
|
-
|
|
90
|
-
or `pointercancel`.
|
|
89
|
+
`{ onCellDown(combo), onCellEnter(combo) }`: call `onCellDown` when a
|
|
90
|
+
pointer goes down on a cell and `onCellEnter` each time it moves onto
|
|
91
|
+
another one. A stroke ends on any window `pointerup` or `pointercancel`.
|
|
91
92
|
- `seedCells(avail, actionWeights, passive): EditorCell[]` — build the
|
|
92
93
|
initial grid from a parent range's per-combo availability (`null` for
|
|
93
94
|
unconstrained) and each action's absolute per-combo weights (the
|
|
@@ -115,7 +116,7 @@ goes in as props and changes come out through `on*Change` callbacks.
|
|
|
115
116
|
is the combo's cap in the parent range and `weights` are each action's
|
|
116
117
|
share of it, summing to 100), `EditorActionSpec`
|
|
117
118
|
(`{ id: string; label: string; color: string }`), `PaintTool`,
|
|
118
|
-
`
|
|
119
|
+
`RangeMatrixEditorProps`, `ActionWeightSlidersProps`,
|
|
119
120
|
`WeightInputProps`.
|
|
120
121
|
|
|
121
122
|
**The editor works at combo level.** A cell is one of the 169 combos (`AKs`,
|
|
@@ -133,7 +134,7 @@ custom property has a default declared on `.spotlab-hm-root`, so the
|
|
|
133
134
|
component renders correctly with zero theming.
|
|
134
135
|
|
|
135
136
|
Because the `className` you pass to a component lands on that same root, a
|
|
136
|
-
class that sets variables works there too (`<
|
|
137
|
+
class that sets variables works there too (`<RangeMatrix className="my-theme" … />`
|
|
137
138
|
with `.my-theme { --spotlab-hm-border: … }`), in addition to the
|
|
138
139
|
`.spotlab-hm-root` selector form below.
|
|
139
140
|
|
|
@@ -195,9 +196,10 @@ Available variables: `--spotlab-hm-border`, `--spotlab-hm-border-width`,
|
|
|
195
196
|
`--spotlab-hm-muted-bg`, `--spotlab-hm-muted-fg`, `--spotlab-hm-track-bg`,
|
|
196
197
|
`--spotlab-hm-row-passive-bg`, `--spotlab-hm-dead-hatch`.
|
|
197
198
|
|
|
198
|
-
Action
|
|
199
|
-
they are data, passed as props.
|
|
200
|
-
when `
|
|
199
|
+
Action colors (each `EditorActionSpec`'s `color`, or `rangeToMatrix`'s
|
|
200
|
+
`color` option) are **not** theme variables — they are data, passed as props.
|
|
201
|
+
`--spotlab-hm-fill` is only the default `rangeToMatrix` uses when `color` is
|
|
202
|
+
omitted.
|
|
201
203
|
|
|
202
204
|
## License
|
|
203
205
|
|
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
+
import { MatrixDisplayProps } from '../hand-matrix';
|
|
2
3
|
import { PaintTool } from './use-range-painting';
|
|
3
4
|
import { EditorCell } from './cells';
|
|
4
|
-
|
|
5
|
-
export type RangeMatrixEditorProps = {
|
|
6
|
-
/** The 169-cell grid, in `@spotlab/range`'s `COMBOS` order. */
|
|
7
|
-
cells: EditorCell[];
|
|
8
|
-
/** Index-aligned with each cell's `weights` array. */
|
|
9
|
-
actions: EditorActionSpec[];
|
|
10
|
-
/** Indices into `actions`/`weights`, in the order bands should stack — a display concern the consumer owns (e.g. biggest raise first). */
|
|
11
|
-
order: number[];
|
|
5
|
+
export type RangeMatrixEditorProps = MatrixDisplayProps & {
|
|
12
6
|
brush: number[];
|
|
13
7
|
tool: PaintTool;
|
|
14
8
|
onCellsChange: (cells: EditorCell[]) => void;
|
|
15
9
|
onBrushChange: (brush: number[]) => void;
|
|
16
10
|
onToolChange: (tool: PaintTool) => void;
|
|
17
|
-
className?: string;
|
|
18
11
|
};
|
|
19
12
|
/**
|
|
20
|
-
* The paintable 13x13 range grid:
|
|
21
|
-
*
|
|
22
|
-
*
|
|
13
|
+
* The paintable 13x13 range grid: `RangeMatrix`'s cells with brush/eyedropper
|
|
14
|
+
* painting wired onto them. Fully controlled; `useRangePainting` drives the
|
|
15
|
+
* state changes.
|
|
23
16
|
*/
|
|
24
17
|
export declare const RangeMatrixEditor: FC<RangeMatrixEditorProps>;
|
package/dist/hand-matrix.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { CSSProperties, FC, PointerEvent as ReactPointerEvent } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type ComboStyleProp = {
|
|
6
|
-
comboStyle?: (combo: string) => CSSProperties;
|
|
7
|
-
};
|
|
2
|
+
import { EditorCell } from './editor/cells';
|
|
3
|
+
import { EditorActionSpec } from './editor/weights';
|
|
4
|
+
type CellPointerHandler = (combo: string, event: ReactPointerEvent<HTMLDivElement>) => void;
|
|
8
5
|
type GridPointerHandlers = {
|
|
9
6
|
/**
|
|
10
7
|
* A pointer (mouse, pen or touch) went down on `combo`'s cell. The grid
|
|
@@ -22,12 +19,29 @@ type GridPointerHandlers = {
|
|
|
22
19
|
*/
|
|
23
20
|
onPointerEnter?: CellPointerHandler;
|
|
24
21
|
};
|
|
22
|
+
/** The cell data both `RangeMatrix` and `RangeMatrixEditor` draw from. */
|
|
23
|
+
export type MatrixDisplayProps = {
|
|
24
|
+
/** The 169-cell grid, in `@spotlab/range`'s `COMBOS` order. */
|
|
25
|
+
cells: EditorCell[];
|
|
26
|
+
/** Index-aligned with each cell's `weights` array. */
|
|
27
|
+
actions: EditorActionSpec[];
|
|
28
|
+
/**
|
|
29
|
+
* Indices into `actions`/`weights`, in the order bands should stack. An
|
|
30
|
+
* action left out isn't drawn, so its share of a cell stays transparent.
|
|
31
|
+
*/
|
|
32
|
+
order: number[];
|
|
33
|
+
className?: string;
|
|
34
|
+
};
|
|
25
35
|
/**
|
|
26
|
-
* The
|
|
27
|
-
*
|
|
28
|
-
*
|
|
36
|
+
* The 13x13 grid that `RangeMatrix` and `RangeMatrixEditor` both render, so
|
|
37
|
+
* the two draw cells identically: each cell stacks its actions' weights as
|
|
38
|
+
* bands in `order`, with dead and capped cells marked. Each cell carries a
|
|
39
|
+
* `data-combo` attribute. The editor adds a per-cell cursor and the painting
|
|
40
|
+
* handlers; passing `onPointerDown` also makes the grid a drag surface
|
|
41
|
+
* (`dragSurfaceStyle`), so a drag reaches the handlers instead of scrolling
|
|
42
|
+
* the page or selecting text. Internal: not exported from the package root.
|
|
29
43
|
*/
|
|
30
|
-
export declare const HandMatrix: FC<{
|
|
31
|
-
|
|
32
|
-
}
|
|
44
|
+
export declare const HandMatrix: FC<MatrixDisplayProps & GridPointerHandlers & {
|
|
45
|
+
cursorOf?: (cell: EditorCell) => CSSProperties["cursor"];
|
|
46
|
+
}>;
|
|
33
47
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { RangeMatrix, type RangeMatrixProps } from './range-matrix';
|
|
2
|
+
export { rangeToMatrix } from './range-to-matrix';
|
|
3
3
|
export { RangeMatrixEditor, type RangeMatrixEditorProps, } from './editor/matrix-editor';
|
|
4
4
|
export { ActionWeightSliders, type ActionWeightSlidersProps, type WeightInputProps, } from './editor/action-sliders';
|
|
5
5
|
export { useRangePainting, type PaintTool } from './editor/use-range-painting';
|
package/dist/index.js
CHANGED
|
@@ -1,364 +1,368 @@
|
|
|
1
|
-
import { useCallback as M, useEffect as
|
|
2
|
-
import { COMBOS as C, comboOf as
|
|
3
|
-
import { jsx as
|
|
4
|
-
var
|
|
5
|
-
const e = t.target;
|
|
6
|
-
e.hasPointerCapture(t.pointerId) && e.releasePointerCapture(t.pointerId);
|
|
7
|
-
}, E = (t, e, n) => {
|
|
8
|
-
const r = t.ownerDocument.elementFromPoint(e, n)?.closest("[data-combo]");
|
|
9
|
-
return !r || !t.contains(r) ? null : r.getAttribute("data-combo");
|
|
10
|
-
}, q = ({ combo: t, onPointerDown: e, comboStyle: n }) => /* @__PURE__ */ g("div", {
|
|
11
|
-
className: "spotlab-hm-cell",
|
|
12
|
-
"data-combo": t,
|
|
13
|
-
style: n?.(t),
|
|
14
|
-
onPointerDown: e && ((r) => {
|
|
15
|
-
j(r), e(t, r);
|
|
16
|
-
}),
|
|
17
|
-
children: /* @__PURE__ */ g("div", {
|
|
18
|
-
className: "spotlab-hm-cell-inner",
|
|
19
|
-
children: /* @__PURE__ */ g("div", {
|
|
20
|
-
"data-combo": t,
|
|
21
|
-
children: t
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
}), G = ({ row: t, ...e }) => /* @__PURE__ */ g("div", {
|
|
25
|
-
className: "spotlab-hm-row",
|
|
26
|
-
children: t.map((n, r) => /* @__PURE__ */ g(q, {
|
|
27
|
-
combo: n,
|
|
28
|
-
...e
|
|
29
|
-
}, r))
|
|
30
|
-
}), U = {
|
|
31
|
-
touchAction: "none",
|
|
32
|
-
userSelect: "none",
|
|
33
|
-
WebkitUserSelect: "none",
|
|
34
|
-
WebkitTouchCallout: "none"
|
|
35
|
-
}, S = ({ className: t, onPointerDown: e, onPointerEnter: n, ...r }) => {
|
|
36
|
-
const a = $(null), o = (c) => {
|
|
37
|
-
const s = E(c.currentTarget, c.clientX, c.clientY);
|
|
38
|
-
s !== a.current && (a.current = s, s && n?.(s, c));
|
|
39
|
-
};
|
|
40
|
-
return /* @__PURE__ */ g("div", {
|
|
41
|
-
className: ["spotlab-hm-root", t].filter(Boolean).join(" "),
|
|
42
|
-
style: e ? U : void 0,
|
|
43
|
-
onPointerDown: n && ((c) => {
|
|
44
|
-
a.current = E(c.currentTarget, c.clientX, c.clientY);
|
|
45
|
-
}),
|
|
46
|
-
onPointerMove: n && o,
|
|
47
|
-
onPointerLeave: n && (() => a.current = null),
|
|
48
|
-
children: X(C, 13).map((c, s) => /* @__PURE__ */ g(G, {
|
|
49
|
-
row: c,
|
|
50
|
-
onPointerDown: e,
|
|
51
|
-
...r
|
|
52
|
-
}, s))
|
|
53
|
-
});
|
|
54
|
-
}, Y = (t, e) => ({ background: L([`${t} 0 ${e * 100}%`, `transparent ${e * 100}% 100%`]) }), ot = ({ range: t, fill: e = "var(--spotlab-hm-fill)", className: n }) => {
|
|
55
|
-
const r = T(() => {
|
|
56
|
-
const a = typeof t == "string" ? F(t) : t;
|
|
57
|
-
return B(a);
|
|
58
|
-
}, [t]);
|
|
59
|
-
return /* @__PURE__ */ g(S, {
|
|
60
|
-
className: n,
|
|
61
|
-
comboStyle: (a) => {
|
|
62
|
-
const o = r.get(a);
|
|
63
|
-
return o ? Y(e, o) : {};
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}, H = (t) => Math.max(0, Math.min(100, Math.round(t))), Q = (t, e) => {
|
|
1
|
+
import { useCallback as M, useEffect as R, useLayoutEffect as L, useRef as y } from "react";
|
|
2
|
+
import { COMBOS as C, comboOf as P, handsOfCombo as T, parseRange as W, toComboWeights as D } from "@spotlab/range";
|
|
3
|
+
import { jsx as v, jsxs as E } from "react/jsx-runtime";
|
|
4
|
+
var B = (t) => Math.max(0, Math.min(100, Math.round(t))), F = (t, r) => {
|
|
67
5
|
const n = t.map(Math.round);
|
|
68
|
-
let
|
|
69
|
-
if (
|
|
70
|
-
for (let a = 0; a < n.length; a++) if (a !==
|
|
71
|
-
n[a] +=
|
|
6
|
+
let e = 100 - n.reduce((a, o) => a + o, 0);
|
|
7
|
+
if (e !== 0) {
|
|
8
|
+
for (let a = 0; a < n.length; a++) if (a !== r && n[a] + e >= 0) {
|
|
9
|
+
n[a] += e, e = 0;
|
|
72
10
|
break;
|
|
73
11
|
}
|
|
74
|
-
if (
|
|
75
|
-
for (let a = 0; a < n.length; a++) if (a !==
|
|
76
|
-
const o = Math.min(n[a], -
|
|
77
|
-
if (n[a] -= o,
|
|
12
|
+
if (e !== 0) {
|
|
13
|
+
for (let a = 0; a < n.length; a++) if (a !== r && n[a] > 0) {
|
|
14
|
+
const o = Math.min(n[a], -e);
|
|
15
|
+
if (n[a] -= o, e += o, e === 0) break;
|
|
78
16
|
}
|
|
79
|
-
n[
|
|
17
|
+
n[r] = Math.max(0, n[r] + e);
|
|
80
18
|
}
|
|
81
19
|
}
|
|
82
20
|
return n;
|
|
83
|
-
},
|
|
84
|
-
const a =
|
|
85
|
-
o[
|
|
86
|
-
const c = 100 - a,
|
|
87
|
-
for (let
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
} else
|
|
94
|
-
return
|
|
95
|
-
}, N = (t,
|
|
96
|
-
const
|
|
97
|
-
return
|
|
98
|
-
}, I = (t,
|
|
21
|
+
}, X = (t, r, n, e) => {
|
|
22
|
+
const a = B(n), o = t.slice();
|
|
23
|
+
o[r] = a;
|
|
24
|
+
const c = 100 - a, i = [];
|
|
25
|
+
for (let l = 0; l < t.length; l++) l !== r && i.push(l);
|
|
26
|
+
const u = i.reduce((l, f) => l + t[f], 0);
|
|
27
|
+
if (u <= 0) {
|
|
28
|
+
i.forEach((f) => o[f] = 0);
|
|
29
|
+
const l = r === e ? i[0] : e;
|
|
30
|
+
l != null && (o[l] = c);
|
|
31
|
+
} else i.forEach((l) => o[l] = Math.round(t[l] / u * c));
|
|
32
|
+
return F(o, r);
|
|
33
|
+
}, N = (t, r) => t.reduce((n, e, a) => a === r ? n : n + e, 0), k = new Map(C.map((t, r) => [t, r])), j = (t, r, n) => {
|
|
34
|
+
const e = t.slice();
|
|
35
|
+
return e[k.get(r)] = n, e;
|
|
36
|
+
}, I = (t, r) => {
|
|
99
37
|
const n = t.slice();
|
|
100
|
-
let
|
|
101
|
-
if (
|
|
102
|
-
const a = 100 /
|
|
103
|
-
for (let o = 0; o < n.length; o++) o !==
|
|
104
|
-
|
|
38
|
+
let e = N(n, r);
|
|
39
|
+
if (e > 100) {
|
|
40
|
+
const a = 100 / e;
|
|
41
|
+
for (let o = 0; o < n.length; o++) o !== r && (n[o] = Math.round(n[o] * a));
|
|
42
|
+
e = N(n, r);
|
|
105
43
|
}
|
|
106
|
-
return n[
|
|
44
|
+
return n[r] = Math.max(0, 100 - e), n;
|
|
107
45
|
};
|
|
108
|
-
function
|
|
109
|
-
return C.map((
|
|
110
|
-
const a = t ? t.get(
|
|
46
|
+
function et(t, r, n) {
|
|
47
|
+
return C.map((e) => {
|
|
48
|
+
const a = t ? t.get(e) ?? 0 : 1, o = r.map(() => 0);
|
|
111
49
|
return a <= 0 ? (o[n] = 100, {
|
|
112
50
|
avail: 0,
|
|
113
51
|
weights: o
|
|
114
|
-
}) : (
|
|
115
|
-
const
|
|
116
|
-
o[
|
|
52
|
+
}) : (r.forEach((c, i) => {
|
|
53
|
+
const u = c?.get(e) ?? 0;
|
|
54
|
+
o[i] = Math.round(u / a * 100);
|
|
117
55
|
}), {
|
|
118
56
|
avail: a,
|
|
119
57
|
weights: I(o, n)
|
|
120
58
|
});
|
|
121
59
|
});
|
|
122
60
|
}
|
|
123
|
-
var
|
|
124
|
-
function
|
|
61
|
+
var S = 8;
|
|
62
|
+
function rt(t, r) {
|
|
125
63
|
const n = /* @__PURE__ */ new Map();
|
|
126
|
-
return t.forEach((
|
|
127
|
-
if (
|
|
128
|
-
const o =
|
|
64
|
+
return t.forEach((e, a) => {
|
|
65
|
+
if (e.avail <= 0) return;
|
|
66
|
+
const o = e.weights.reduce((i, u) => i + u, 0);
|
|
129
67
|
if (!o) return;
|
|
130
|
-
const c = Number((
|
|
68
|
+
const c = Number((e.weights[r] / o * e.avail).toFixed(S));
|
|
131
69
|
c && n.set(C[a], c);
|
|
132
70
|
}), n;
|
|
133
71
|
}
|
|
134
|
-
function
|
|
135
|
-
return t.map((
|
|
136
|
-
const o =
|
|
137
|
-
if (
|
|
72
|
+
function nt(t, r, n) {
|
|
73
|
+
return t.map((e, a) => {
|
|
74
|
+
const o = r.map(() => 0);
|
|
75
|
+
if (e.avail <= 0)
|
|
138
76
|
return o[n] = 100, {
|
|
139
|
-
avail:
|
|
77
|
+
avail: e.avail,
|
|
140
78
|
weights: o
|
|
141
79
|
};
|
|
142
80
|
const c = C[a];
|
|
143
|
-
return
|
|
144
|
-
const
|
|
145
|
-
o[
|
|
81
|
+
return r.forEach((i, u) => {
|
|
82
|
+
const l = i?.get(c) ?? 0;
|
|
83
|
+
o[u] = Math.round(l / e.avail * 100);
|
|
146
84
|
}), {
|
|
147
|
-
avail:
|
|
85
|
+
avail: e.avail,
|
|
148
86
|
weights: I(o, n)
|
|
149
87
|
};
|
|
150
88
|
});
|
|
151
89
|
}
|
|
152
|
-
var
|
|
153
|
-
function
|
|
154
|
-
const a =
|
|
155
|
-
const b = Number(
|
|
90
|
+
var q = (t, r) => t.avail !== r.avail || t.weights.length !== r.weights.length || t.weights.some((n, e) => n !== r.weights[e]);
|
|
91
|
+
function at(t, r, n, e) {
|
|
92
|
+
const a = e && new Map(e.map(({ hand: s, frequency: h }) => [s, h])), o = (s, h) => e === void 0 ? h.avail : a ? a.get(s) ?? 0 : 1, c = t.map((s) => s && new Map(s.map(({ hand: h, frequency: g }) => [h, g]))), i = (s) => c.reduce((h, g) => h + (g?.get(s) ?? 0), 0), u = t.flatMap((s, h) => s ? [] : [h]), l = (s, h) => T(s).flatMap((g) => {
|
|
93
|
+
const b = Number(h(g).toFixed(S));
|
|
156
94
|
return b > 0 ? [{
|
|
157
|
-
hand:
|
|
95
|
+
hand: g,
|
|
158
96
|
frequency: b
|
|
159
97
|
}] : [];
|
|
160
|
-
}),
|
|
161
|
-
const
|
|
162
|
-
return
|
|
163
|
-
},
|
|
164
|
-
const
|
|
165
|
-
return
|
|
166
|
-
},
|
|
167
|
-
return t.map((
|
|
168
|
-
if (
|
|
169
|
-
const
|
|
170
|
-
for (const
|
|
171
|
-
const w =
|
|
172
|
-
|
|
98
|
+
}), f = (s, h) => {
|
|
99
|
+
const g = n[k.get(s)], b = g.weights.reduce((m, w) => m + w, 0);
|
|
100
|
+
return g.avail <= 0 || !b ? [] : l(s, (m) => g.weights[h] / b * o(m, g));
|
|
101
|
+
}, p = (s, h) => {
|
|
102
|
+
const g = n[k.get(s)], b = u.reduce((w, O) => w + g.weights[O], 0), m = b ? g.weights[h] / b : 1 / u.length;
|
|
103
|
+
return l(s, (w) => Math.max(0, o(w, g) - i(w)) * m);
|
|
104
|
+
}, d = new Set(C.filter((s, h) => q(r[h], n[h])));
|
|
105
|
+
return t.map((s, h) => {
|
|
106
|
+
if (s === null) return C.flatMap((m) => d.has(m) ? f(m, h) : p(m, h));
|
|
107
|
+
const g = [], b = /* @__PURE__ */ new Set();
|
|
108
|
+
for (const m of s) {
|
|
109
|
+
const w = P(m.hand);
|
|
110
|
+
d.has(w) ? b.has(w) || (b.add(w), g.push(...f(w, h))) : g.push(m);
|
|
173
111
|
}
|
|
174
|
-
for (const
|
|
175
|
-
return
|
|
112
|
+
for (const m of d) b.has(m) || g.push(...f(m, h));
|
|
113
|
+
return g;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
var _ = (t, r) => Array.from({ length: Math.ceil(t.length / r) }, (n, e) => t.slice(e * r, e * r + r)), U = (t) => `linear-gradient(to right, ${t.join(", ")})`, $ = (t, r, n) => {
|
|
117
|
+
const e = [];
|
|
118
|
+
let a = 0;
|
|
119
|
+
return n.forEach((o) => {
|
|
120
|
+
const c = (t.weights[o] || 0) / 100;
|
|
121
|
+
if (c <= 0) return;
|
|
122
|
+
const i = r[o].color;
|
|
123
|
+
e.push(`${i} ${a * 100}%`), e.push(`${i} ${(a + c) * 100}%`), a += c;
|
|
124
|
+
}), e.length > 0 && a < 1 - 1e-9 && e.push(`transparent ${a * 100}% 100%`), e.length > 0 ? U(e) : "none";
|
|
125
|
+
}, Y = (t, r, n) => {
|
|
126
|
+
if (t.avail <= 0) return {
|
|
127
|
+
backgroundImage: "var(--spotlab-hm-dead-hatch)",
|
|
128
|
+
backgroundColor: "var(--spotlab-hm-muted-bg)",
|
|
129
|
+
color: "var(--spotlab-hm-muted-fg)"
|
|
130
|
+
};
|
|
131
|
+
if (t.avail < 1) {
|
|
132
|
+
const e = `${t.avail * 100}%`;
|
|
133
|
+
return {
|
|
134
|
+
backgroundImage: `repeating-linear-gradient(180deg, var(--spotlab-hm-muted-fg) 0 4px, transparent 4px 8px), var(--spotlab-hm-dead-hatch), ${$(t, r, n)}`,
|
|
135
|
+
backgroundSize: `1px 100%, ${(1 - t.avail) * 100}% 100%, ${t.avail * 100}% 100%`,
|
|
136
|
+
backgroundPosition: `${e} center, right center, left center`,
|
|
137
|
+
backgroundRepeat: "no-repeat, no-repeat, no-repeat"
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return { backgroundImage: $(t, r, n) };
|
|
141
|
+
}, G = (t) => {
|
|
142
|
+
const r = t.target;
|
|
143
|
+
r.hasPointerCapture(t.pointerId) && r.releasePointerCapture(t.pointerId);
|
|
144
|
+
}, x = (t, r, n) => {
|
|
145
|
+
const e = t.ownerDocument.elementFromPoint(r, n)?.closest("[data-combo]");
|
|
146
|
+
return !e || !t.contains(e) ? null : e.getAttribute("data-combo");
|
|
147
|
+
}, H = {
|
|
148
|
+
touchAction: "none",
|
|
149
|
+
userSelect: "none",
|
|
150
|
+
WebkitUserSelect: "none",
|
|
151
|
+
WebkitTouchCallout: "none"
|
|
152
|
+
}, A = ({ cells: t, actions: r, order: n, className: e, cursorOf: a, onPointerDown: o, onPointerEnter: c }) => {
|
|
153
|
+
const i = y(null), u = (l) => {
|
|
154
|
+
const f = x(l.currentTarget, l.clientX, l.clientY);
|
|
155
|
+
f !== i.current && (i.current = f, f && c?.(f, l));
|
|
156
|
+
};
|
|
157
|
+
return /* @__PURE__ */ v("div", {
|
|
158
|
+
className: ["spotlab-hm-root", e].filter(Boolean).join(" "),
|
|
159
|
+
style: o ? H : void 0,
|
|
160
|
+
onPointerDown: c && ((l) => {
|
|
161
|
+
i.current = x(l.currentTarget, l.clientX, l.clientY);
|
|
162
|
+
}),
|
|
163
|
+
onPointerMove: c && u,
|
|
164
|
+
onPointerLeave: c && (() => i.current = null),
|
|
165
|
+
children: _(C, 13).map((l, f) => /* @__PURE__ */ v("div", {
|
|
166
|
+
className: "spotlab-hm-row",
|
|
167
|
+
children: l.map((p) => {
|
|
168
|
+
const d = t[k.get(p)];
|
|
169
|
+
return /* @__PURE__ */ v("div", {
|
|
170
|
+
className: "spotlab-hm-cell",
|
|
171
|
+
"data-combo": p,
|
|
172
|
+
style: {
|
|
173
|
+
...Y(d, r, n),
|
|
174
|
+
cursor: a?.(d)
|
|
175
|
+
},
|
|
176
|
+
onPointerDown: o && ((s) => {
|
|
177
|
+
G(s), o(p, s);
|
|
178
|
+
}),
|
|
179
|
+
children: /* @__PURE__ */ v("div", {
|
|
180
|
+
className: "spotlab-hm-cell-inner",
|
|
181
|
+
children: /* @__PURE__ */ v("div", {
|
|
182
|
+
"data-combo": p,
|
|
183
|
+
children: p
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
}, p);
|
|
187
|
+
})
|
|
188
|
+
}, f))
|
|
176
189
|
});
|
|
190
|
+
}, ot = A;
|
|
191
|
+
function lt(t, { color: r = "var(--spotlab-hm-fill)", labels: n = {} } = {}) {
|
|
192
|
+
const e = D(typeof t == "string" ? W(t) : t);
|
|
193
|
+
return {
|
|
194
|
+
cells: C.map((a) => {
|
|
195
|
+
const o = (e.get(a) ?? 0) * 100;
|
|
196
|
+
return {
|
|
197
|
+
avail: 1,
|
|
198
|
+
weights: [o, 100 - o]
|
|
199
|
+
};
|
|
200
|
+
}),
|
|
201
|
+
actions: [{
|
|
202
|
+
id: "in",
|
|
203
|
+
label: n.in ?? "In range",
|
|
204
|
+
color: r
|
|
205
|
+
}, {
|
|
206
|
+
id: "out",
|
|
207
|
+
label: n.out ?? "Out of range",
|
|
208
|
+
color: "transparent"
|
|
209
|
+
}],
|
|
210
|
+
order: [0]
|
|
211
|
+
};
|
|
177
212
|
}
|
|
178
|
-
function
|
|
179
|
-
const { cells:
|
|
180
|
-
|
|
213
|
+
function Q(t) {
|
|
214
|
+
const { cells: r, brush: n, tool: e, onCellsChange: a, onBrushChange: o, onToolChange: c } = t, i = y(null), u = M(() => {
|
|
215
|
+
i.current?.abort(), i.current = null;
|
|
181
216
|
}, []);
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}, [
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
190
|
-
const
|
|
191
|
-
avail:
|
|
217
|
+
R(() => u, [u]);
|
|
218
|
+
const l = y(r);
|
|
219
|
+
L(() => {
|
|
220
|
+
l.current = r;
|
|
221
|
+
}, [r]);
|
|
222
|
+
const f = M((d) => {
|
|
223
|
+
const s = l.current, { avail: h } = s[k.get(d)];
|
|
224
|
+
if (h <= 0) return;
|
|
225
|
+
const g = j(s, d, {
|
|
226
|
+
avail: h,
|
|
192
227
|
weights: [...n]
|
|
193
228
|
});
|
|
194
|
-
|
|
195
|
-
}, [n, a]),
|
|
196
|
-
const
|
|
197
|
-
|
|
229
|
+
l.current = g, a(g);
|
|
230
|
+
}, [n, a]), p = M((d) => {
|
|
231
|
+
const s = k.get(d);
|
|
232
|
+
r[s].avail <= 0 || (o([...r[s].weights]), c("brush"));
|
|
198
233
|
}, [
|
|
199
|
-
|
|
234
|
+
r,
|
|
200
235
|
o,
|
|
201
236
|
c
|
|
202
237
|
]);
|
|
203
238
|
return {
|
|
204
|
-
onCellDown: M((
|
|
205
|
-
if (
|
|
206
|
-
|
|
239
|
+
onCellDown: M((d) => {
|
|
240
|
+
if (e === "eyedropper") {
|
|
241
|
+
p(d);
|
|
207
242
|
return;
|
|
208
243
|
}
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
244
|
+
u();
|
|
245
|
+
const s = new AbortController();
|
|
246
|
+
i.current = s, window.addEventListener("pointerup", u, { signal: s.signal }), window.addEventListener("pointercancel", u, { signal: s.signal }), f(d);
|
|
212
247
|
}, [
|
|
213
|
-
|
|
214
|
-
m,
|
|
248
|
+
e,
|
|
215
249
|
p,
|
|
216
|
-
|
|
250
|
+
f,
|
|
251
|
+
u
|
|
217
252
|
]),
|
|
218
|
-
onCellEnter: M((
|
|
219
|
-
|
|
220
|
-
}, [
|
|
253
|
+
onCellEnter: M((d) => {
|
|
254
|
+
i.current && e === "brush" && f(d);
|
|
255
|
+
}, [e, f])
|
|
221
256
|
};
|
|
222
257
|
}
|
|
223
|
-
var
|
|
224
|
-
const
|
|
225
|
-
let a = 0;
|
|
226
|
-
return n.forEach((o) => {
|
|
227
|
-
const c = (t.weights[o] || 0) / 100;
|
|
228
|
-
if (c <= 0) return;
|
|
229
|
-
const s = e[o].color;
|
|
230
|
-
r.push(`${s} ${a * 100}%`), r.push(`${s} ${(a + c) * 100}%`), a += c;
|
|
231
|
-
}), r.length > 0 && a < 1 - 1e-9 && r.push(`transparent ${a * 100}% 100%`), L(r);
|
|
232
|
-
}, ut = ({ cells: t, actions: e, order: n, brush: r, tool: a, onCellsChange: o, onBrushChange: c, onToolChange: s, className: d }) => {
|
|
233
|
-
const { onCellDown: h, onCellEnter: p } = Z({
|
|
258
|
+
var st = ({ cells: t, actions: r, order: n, brush: e, tool: a, onCellsChange: o, onBrushChange: c, onToolChange: i, className: u }) => {
|
|
259
|
+
const { onCellDown: l, onCellEnter: f } = Q({
|
|
234
260
|
cells: t,
|
|
235
|
-
brush:
|
|
261
|
+
brush: e,
|
|
236
262
|
tool: a,
|
|
237
263
|
onCellsChange: o,
|
|
238
264
|
onBrushChange: c,
|
|
239
|
-
onToolChange:
|
|
265
|
+
onToolChange: i
|
|
240
266
|
});
|
|
241
|
-
return /* @__PURE__ */
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
color: "var(--spotlab-hm-muted-fg)"
|
|
250
|
-
};
|
|
251
|
-
const l = a === "eyedropper" ? "copy" : "pointer";
|
|
252
|
-
if (u.avail < 1) {
|
|
253
|
-
const i = `${u.avail * 100}%`;
|
|
254
|
-
return {
|
|
255
|
-
background: `repeating-linear-gradient(180deg, var(--spotlab-hm-muted-fg) 0 4px, transparent 4px 8px), var(--spotlab-hm-dead-hatch), ${R(u, e, n)}`,
|
|
256
|
-
backgroundSize: `1px 100%, ${(1 - u.avail) * 100}% 100%, ${u.avail * 100}% 100%`,
|
|
257
|
-
backgroundPosition: `${i} center, right center, left center`,
|
|
258
|
-
backgroundRepeat: "no-repeat, no-repeat, no-repeat",
|
|
259
|
-
cursor: l
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
background: R(u, e, n),
|
|
264
|
-
cursor: l
|
|
265
|
-
};
|
|
266
|
-
},
|
|
267
|
-
onPointerDown: h,
|
|
268
|
-
onPointerEnter: p
|
|
267
|
+
return /* @__PURE__ */ v(A, {
|
|
268
|
+
cells: t,
|
|
269
|
+
actions: r,
|
|
270
|
+
order: n,
|
|
271
|
+
className: u,
|
|
272
|
+
cursorOf: (p) => p.avail <= 0 ? "not-allowed" : a === "eyedropper" ? "copy" : "pointer",
|
|
273
|
+
onPointerDown: l,
|
|
274
|
+
onPointerEnter: f
|
|
269
275
|
});
|
|
270
|
-
},
|
|
276
|
+
}, J = (t) => /* @__PURE__ */ v("input", {
|
|
271
277
|
type: "number",
|
|
272
278
|
className: "spotlab-hm-weight-input",
|
|
273
279
|
...t
|
|
274
|
-
}),
|
|
275
|
-
const a =
|
|
276
|
-
const
|
|
277
|
-
if (!
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
}, [
|
|
281
|
-
return
|
|
282
|
-
const
|
|
283
|
-
o.current && c(
|
|
284
|
-
},
|
|
285
|
-
return window.addEventListener("pointermove",
|
|
286
|
-
window.removeEventListener("pointermove",
|
|
280
|
+
}), K = ({ value: t, color: r, passive: n, onChange: e }) => {
|
|
281
|
+
const a = y(null), o = y(!1), c = M((i) => {
|
|
282
|
+
const u = a.current;
|
|
283
|
+
if (!u) return;
|
|
284
|
+
const l = u.getBoundingClientRect();
|
|
285
|
+
e((i - l.left) / l.width * 100);
|
|
286
|
+
}, [e]);
|
|
287
|
+
return R(() => {
|
|
288
|
+
const i = (l) => {
|
|
289
|
+
o.current && c(l.clientX);
|
|
290
|
+
}, u = () => o.current = !1;
|
|
291
|
+
return window.addEventListener("pointermove", i), window.addEventListener("pointerup", u), () => {
|
|
292
|
+
window.removeEventListener("pointermove", i), window.removeEventListener("pointerup", u);
|
|
287
293
|
};
|
|
288
|
-
}, [c]), /* @__PURE__ */
|
|
294
|
+
}, [c]), /* @__PURE__ */ v("div", {
|
|
289
295
|
ref: a,
|
|
290
296
|
role: "slider",
|
|
291
297
|
"aria-valuenow": t,
|
|
292
298
|
"aria-valuemin": 0,
|
|
293
299
|
"aria-valuemax": 100,
|
|
294
300
|
className: "spotlab-hm-slider-track",
|
|
295
|
-
style: { background: `linear-gradient(to right, ${
|
|
296
|
-
onPointerDown: (
|
|
297
|
-
o.current = !0, c(
|
|
301
|
+
style: { background: `linear-gradient(to right, ${r} 0 ${t}%, var(--spotlab-hm-track-bg) ${t}% 100%)` },
|
|
302
|
+
onPointerDown: (i) => {
|
|
303
|
+
o.current = !0, c(i.clientX);
|
|
298
304
|
},
|
|
299
|
-
children: /* @__PURE__ */
|
|
305
|
+
children: /* @__PURE__ */ v("div", {
|
|
300
306
|
className: "spotlab-hm-slider-thumb",
|
|
301
307
|
style: {
|
|
302
308
|
left: `${t}%`,
|
|
303
|
-
border: `2px solid ${n ? "var(--spotlab-hm-muted-fg)" :
|
|
309
|
+
border: `2px solid ${n ? "var(--spotlab-hm-muted-fg)" : r}`
|
|
304
310
|
}
|
|
305
311
|
})
|
|
306
312
|
});
|
|
307
|
-
},
|
|
313
|
+
}, V = (t, r) => /* @__PURE__ */ E("span", {
|
|
308
314
|
className: "spotlab-hm-slider-label",
|
|
309
|
-
children: [t.label,
|
|
315
|
+
children: [t.label, r && /* @__PURE__ */ v("span", {
|
|
310
316
|
className: "spotlab-hm-slider-remainder",
|
|
311
317
|
children: " · remainder"
|
|
312
318
|
})]
|
|
313
|
-
}),
|
|
314
|
-
const
|
|
315
|
-
a(
|
|
319
|
+
}), it = ({ actions: t, order: r, weights: n, passive: e, onWeightsChange: a, renderActionLabel: o, renderActionExtra: c, components: i, className: u }) => {
|
|
320
|
+
const l = i?.WeightInput ?? J, f = (p, d) => {
|
|
321
|
+
a(X(n, p, d, e));
|
|
316
322
|
};
|
|
317
|
-
return /* @__PURE__ */
|
|
318
|
-
className: ["spotlab-hm-root spotlab-hm-sliders",
|
|
319
|
-
children:
|
|
320
|
-
const
|
|
321
|
-
return /* @__PURE__ */
|
|
323
|
+
return /* @__PURE__ */ v("div", {
|
|
324
|
+
className: ["spotlab-hm-root spotlab-hm-sliders", u].filter(Boolean).join(" "),
|
|
325
|
+
children: r.map((p) => {
|
|
326
|
+
const d = t[p], s = p === e;
|
|
327
|
+
return /* @__PURE__ */ E("div", {
|
|
322
328
|
className: "spotlab-hm-slider-row",
|
|
323
|
-
"data-passive":
|
|
324
|
-
children: [/* @__PURE__ */
|
|
329
|
+
"data-passive": s,
|
|
330
|
+
children: [/* @__PURE__ */ E("div", {
|
|
325
331
|
className: "spotlab-hm-slider-header",
|
|
326
332
|
children: [
|
|
327
|
-
/* @__PURE__ */
|
|
333
|
+
/* @__PURE__ */ v("span", {
|
|
328
334
|
className: "spotlab-hm-slider-swatch",
|
|
329
|
-
style: { background:
|
|
335
|
+
style: { background: d.color }
|
|
330
336
|
}),
|
|
331
|
-
o?.(
|
|
332
|
-
c?.(
|
|
337
|
+
o?.(d, p, s) ?? V(d, s),
|
|
338
|
+
c?.(d, p)
|
|
333
339
|
]
|
|
334
|
-
}), /* @__PURE__ */
|
|
340
|
+
}), /* @__PURE__ */ E("div", {
|
|
335
341
|
className: "spotlab-hm-slider-track-row",
|
|
336
|
-
children: [/* @__PURE__ */
|
|
337
|
-
value: n[
|
|
338
|
-
color:
|
|
339
|
-
passive:
|
|
340
|
-
onChange: (
|
|
341
|
-
}), /* @__PURE__ */
|
|
342
|
-
value: n[
|
|
343
|
-
"aria-label": `${
|
|
344
|
-
onChange: (
|
|
342
|
+
children: [/* @__PURE__ */ v(K, {
|
|
343
|
+
value: n[p],
|
|
344
|
+
color: d.color,
|
|
345
|
+
passive: s,
|
|
346
|
+
onChange: (h) => f(p, h)
|
|
347
|
+
}), /* @__PURE__ */ v(l, {
|
|
348
|
+
value: n[p],
|
|
349
|
+
"aria-label": `${d.label} weight`,
|
|
350
|
+
onChange: (h) => f(p, parseInt(h.target.value || "0", 10))
|
|
345
351
|
})]
|
|
346
352
|
})]
|
|
347
|
-
},
|
|
353
|
+
}, d.id);
|
|
348
354
|
})
|
|
349
355
|
});
|
|
350
356
|
};
|
|
351
357
|
export {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
lt as seedCells,
|
|
363
|
-
Z as useRangePainting
|
|
358
|
+
it as ActionWeightSliders,
|
|
359
|
+
ot as RangeMatrix,
|
|
360
|
+
st as RangeMatrixEditor,
|
|
361
|
+
rt as cellsToComboWeights,
|
|
362
|
+
at as cellsToRanges,
|
|
363
|
+
nt as comboWeightsToCells,
|
|
364
|
+
lt as rangeToMatrix,
|
|
365
|
+
X as rebalance,
|
|
366
|
+
et as seedCells,
|
|
367
|
+
Q as useRangePainting
|
|
364
368
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { MatrixDisplayProps } from './hand-matrix';
|
|
3
|
+
export type RangeMatrixProps = MatrixDisplayProps;
|
|
4
|
+
/**
|
|
5
|
+
* A read-only 13x13 grid of several actions at once: each cell stacks its
|
|
6
|
+
* actions' weights as colored bands in `order`, hatches dead cells (`avail`
|
|
7
|
+
* 0), and marks capped cells (`avail` below 1) with a cap line and hatched
|
|
8
|
+
* remainder. Draws exactly what `RangeMatrixEditor` does, without painting.
|
|
9
|
+
*/
|
|
10
|
+
export declare const RangeMatrix: FC<RangeMatrixProps>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HandFrequency } from '@spotlab/range';
|
|
2
|
+
import { RangeMatrixProps } from './range-matrix';
|
|
3
|
+
/**
|
|
4
|
+
* `RangeMatrix`'s props for drawing one range: every cell is fully available
|
|
5
|
+
* and filled to its combo's mean weight in `color` (default
|
|
6
|
+
* `var(--spotlab-hm-fill)`), with the rest left blank. The two actions are
|
|
7
|
+
* `in` and `out`, labeled `labels.in` (default "In range") and `labels.out`
|
|
8
|
+
* (default "Out of range") for a legend of your own. Takes a range string or
|
|
9
|
+
* its expanded hand-keyed form; a string is parsed via `@spotlab/range`, so
|
|
10
|
+
* `initRange()` must have resolved. Parsing and collapsing are wasm calls, so
|
|
11
|
+
* memoize the result rather than calling this on every render.
|
|
12
|
+
*/
|
|
13
|
+
export declare function rangeToMatrix(range: HandFrequency[] | string, { color, labels, }?: {
|
|
14
|
+
color?: string;
|
|
15
|
+
labels?: {
|
|
16
|
+
in?: string;
|
|
17
|
+
out?: string;
|
|
18
|
+
};
|
|
19
|
+
}): Omit<RangeMatrixProps, "className">;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spotlab/hand-matrix",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A 13x13 poker hand-matrix React component: the read-only grid primitive and a range-string-aware display component, themed through CSS custom properties.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/dist/range-grid.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { HandFrequency } from '@spotlab/range';
|
|
3
|
-
/**
|
|
4
|
-
* A read-only 13x13 range grid: each cell fills to its combo's mean weight.
|
|
5
|
-
* Accepts the expanded hand-keyed form or a range string directly — a range
|
|
6
|
-
* string is parsed via `@spotlab/range`, so the caller never needs to touch
|
|
7
|
-
* the parser itself to render one.
|
|
8
|
-
*/
|
|
9
|
-
export declare const RangeGrid: FC<{
|
|
10
|
-
range: HandFrequency[] | string;
|
|
11
|
-
fill?: string;
|
|
12
|
-
className?: string;
|
|
13
|
-
}>;
|