react-cheminfo 0.21.0 → 0.23.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 +14 -4
- package/lib/build/vite/gitHead.d.ts.map +1 -1
- package/lib/build/vite/gitHead.js +17 -2
- package/lib/build/vite/gitHead.js.map +1 -1
- package/lib/clipboard/ui/ClickToCopy.d.ts +69 -0
- package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -0
- package/lib/clipboard/ui/ClickToCopy.js +66 -0
- package/lib/clipboard/ui/ClickToCopy.js.map +1 -0
- package/lib/clipboard/ui/CopyButton.d.ts +1 -1
- package/lib/clipboard/ui/CopyButton.js +1 -1
- package/lib/clipboard/ui/CopyableValue.d.ts +3 -3
- package/lib/clipboard/ui/CopyableValue.d.ts.map +1 -1
- package/lib/clipboard/ui/CopyableValue.js +5 -5
- package/lib/clipboard/ui/CopyableValue.js.map +1 -1
- package/lib/clipboard/ui/index.d.ts +2 -0
- package/lib/clipboard/ui/index.d.ts.map +1 -1
- package/lib/clipboard/ui/index.js +1 -0
- package/lib/clipboard/ui/index.js.map +1 -1
- package/lib/ecosystem/core/groups.d.ts +4 -3
- package/lib/ecosystem/core/groups.d.ts.map +1 -1
- package/lib/ecosystem/core/groups.js +8 -2
- package/lib/ecosystem/core/groups.js.map +1 -1
- package/lib/ecosystem/core/sites.d.ts.map +1 -1
- package/lib/ecosystem/core/sites.js +39 -0
- package/lib/ecosystem/core/sites.js.map +1 -1
- package/lib/ecosystem/core/types.d.ts +1 -1
- package/lib/ecosystem/core/types.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.js +9 -0
- package/lib/ecosystem/ui/glyphs.js.map +1 -1
- package/lib/error/ui/ErrorFallback.d.ts.map +1 -1
- package/lib/error/ui/ErrorFallback.js +1 -1
- package/lib/error/ui/ErrorFallback.js.map +1 -1
- package/lib/overlay/core/index.d.ts +2 -2
- package/lib/overlay/core/index.d.ts.map +1 -1
- package/lib/overlay/core/index.js +1 -1
- package/lib/overlay/core/index.js.map +1 -1
- package/lib/overlay/core/overlayMarks.d.ts +20 -5
- package/lib/overlay/core/overlayMarks.d.ts.map +1 -1
- package/lib/overlay/core/overlayMarks.js +31 -5
- package/lib/overlay/core/overlayMarks.js.map +1 -1
- package/lib/overlay/ui/OverlayLegendMark.js +5 -0
- package/lib/overlay/ui/OverlayLegendMark.js.map +1 -1
- package/lib/pedagogy/ui/ReferenceSectionBlock.d.ts.map +1 -1
- package/lib/pedagogy/ui/ReferenceSectionBlock.js +2 -1
- package/lib/pedagogy/ui/ReferenceSectionBlock.js.map +1 -1
- package/lib/projection/core/index.d.ts +4 -4
- package/lib/projection/core/index.d.ts.map +1 -1
- package/lib/projection/core/index.js +2 -2
- package/lib/projection/core/index.js.map +1 -1
- package/lib/projection/core/projectionCopy.d.ts +2 -0
- package/lib/projection/core/projectionCopy.d.ts.map +1 -1
- package/lib/projection/core/projectionCopy.js +1 -0
- package/lib/projection/core/projectionCopy.js.map +1 -1
- package/lib/projection/core/projectionGroupings.d.ts +44 -0
- package/lib/projection/core/projectionGroupings.d.ts.map +1 -0
- package/lib/projection/core/projectionGroupings.js +132 -0
- package/lib/projection/core/projectionGroupings.js.map +1 -0
- package/lib/projection/core/projectionOptions.d.ts +16 -6
- package/lib/projection/core/projectionOptions.d.ts.map +1 -1
- package/lib/projection/core/projectionOptions.js +7 -1
- package/lib/projection/core/projectionOptions.js.map +1 -1
- package/lib/projection/core/projectionPanelWords.d.ts +6 -0
- package/lib/projection/core/projectionPanelWords.d.ts.map +1 -1
- package/lib/projection/core/projectionPanelWords.js +4 -0
- package/lib/projection/core/projectionPanelWords.js.map +1 -1
- package/lib/projection/core/projectionSamples.d.ts +63 -32
- package/lib/projection/core/projectionSamples.d.ts.map +1 -1
- package/lib/projection/core/projectionSamples.js +1 -80
- package/lib/projection/core/projectionSamples.js.map +1 -1
- package/lib/projection/core/projectionStrings.d.ts +2 -0
- package/lib/projection/core/projectionStrings.d.ts.map +1 -1
- package/lib/projection/core/projectionStrings.js +10 -1
- package/lib/projection/core/projectionStrings.js.map +1 -1
- package/lib/projection/core/resolveProjectionOptions.d.ts +8 -3
- package/lib/projection/core/resolveProjectionOptions.d.ts.map +1 -1
- package/lib/projection/core/resolveProjectionOptions.js +58 -5
- package/lib/projection/core/resolveProjectionOptions.js.map +1 -1
- package/lib/projection/ui/ProjectionBar.d.ts +1 -1
- package/lib/projection/ui/ProjectionBar.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionBar.js +3 -1
- package/lib/projection/ui/ProjectionBar.js.map +1 -1
- package/lib/projection/ui/ProjectionGroupingPickers.d.ts +38 -0
- package/lib/projection/ui/ProjectionGroupingPickers.d.ts.map +1 -0
- package/lib/projection/ui/ProjectionGroupingPickers.js +33 -0
- package/lib/projection/ui/ProjectionGroupingPickers.js.map +1 -0
- package/lib/projection/ui/ProjectionMapControls.d.ts +6 -7
- package/lib/projection/ui/ProjectionMapControls.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionMapControls.js +11 -9
- package/lib/projection/ui/ProjectionMapControls.js.map +1 -1
- package/lib/projection/ui/ProjectionMapLegend.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionMapLegend.js +1 -1
- package/lib/projection/ui/ProjectionMapLegend.js.map +1 -1
- package/lib/projection/ui/ProjectionMapMore.d.ts +2 -2
- package/lib/projection/ui/ProjectionMapMore.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionMapMore.js +7 -5
- package/lib/projection/ui/ProjectionMapMore.js.map +1 -1
- package/lib/projection/ui/ProjectionMapTab.d.ts +15 -6
- package/lib/projection/ui/ProjectionMapTab.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionMapTab.js +11 -7
- package/lib/projection/ui/ProjectionMapTab.js.map +1 -1
- package/lib/projection/ui/ProjectionPairsMore.d.ts +3 -7
- package/lib/projection/ui/ProjectionPairsMore.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionPairsMore.js +4 -5
- package/lib/projection/ui/ProjectionPairsMore.js.map +1 -1
- package/lib/projection/ui/ProjectionPairsTab.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionPairsTab.js +2 -2
- package/lib/projection/ui/ProjectionPairsTab.js.map +1 -1
- package/lib/projection/ui/ProjectionPanel.d.ts +1 -1
- package/lib/projection/ui/ProjectionPanel.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionPanel.js +1 -1
- package/lib/projection/ui/ProjectionPanel.js.map +1 -1
- package/lib/projection/ui/ProjectionReadout.d.ts +7 -1
- package/lib/projection/ui/ProjectionReadout.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionReadout.js +19 -7
- package/lib/projection/ui/ProjectionReadout.js.map +1 -1
- package/lib/projection/ui/ProjectionSpaceControls.d.ts +3 -5
- package/lib/projection/ui/ProjectionSpaceControls.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionSpaceControls.js +9 -7
- package/lib/projection/ui/ProjectionSpaceControls.js.map +1 -1
- package/lib/projection/ui/ProjectionSpaceMore.d.ts +2 -2
- package/lib/projection/ui/ProjectionSpaceMore.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionSpaceMore.js +5 -4
- package/lib/projection/ui/ProjectionSpaceMore.js.map +1 -1
- package/lib/projection/ui/ProjectionSpaceTab.d.ts +11 -3
- package/lib/projection/ui/ProjectionSpaceTab.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionSpaceTab.js +7 -4
- package/lib/projection/ui/ProjectionSpaceTab.js.map +1 -1
- package/lib/projection/ui/ProjectionViewer.d.ts.map +1 -1
- package/lib/projection/ui/ProjectionViewer.js +1 -0
- package/lib/projection/ui/ProjectionViewer.js.map +1 -1
- package/lib/projection/ui/projectionBarReadings.d.ts +4 -1
- package/lib/projection/ui/projectionBarReadings.d.ts.map +1 -1
- package/lib/projection/ui/projectionBarReadings.js +14 -4
- package/lib/projection/ui/projectionBarReadings.js.map +1 -1
- package/lib/projection/ui/projectionBarSlots.d.ts +4 -2
- package/lib/projection/ui/projectionBarSlots.d.ts.map +1 -1
- package/lib/projection/ui/projectionBarSlots.js +3 -7
- package/lib/projection/ui/projectionBarSlots.js.map +1 -1
- package/lib/projection/ui/projectionMapChoices.d.ts +31 -6
- package/lib/projection/ui/projectionMapChoices.d.ts.map +1 -1
- package/lib/projection/ui/projectionMapChoices.js +58 -9
- package/lib/projection/ui/projectionMapChoices.js.map +1 -1
- package/lib/projection/ui/projectionMapChrome.d.ts +3 -9
- package/lib/projection/ui/projectionMapChrome.d.ts.map +1 -1
- package/lib/projection/ui/projectionMapChrome.js +41 -27
- package/lib/projection/ui/projectionMapChrome.js.map +1 -1
- package/lib/projection/ui/projectionMapCorner.d.ts +25 -0
- package/lib/projection/ui/projectionMapCorner.d.ts.map +1 -0
- package/lib/projection/ui/projectionMapCorner.js +46 -0
- package/lib/projection/ui/projectionMapCorner.js.map +1 -0
- package/lib/projection/ui/projectionMapModel.d.ts +9 -18
- package/lib/projection/ui/projectionMapModel.d.ts.map +1 -1
- package/lib/projection/ui/projectionMapModel.js +14 -39
- package/lib/projection/ui/projectionMapModel.js.map +1 -1
- package/lib/projection/ui/projectionMapView.d.ts +3 -1
- package/lib/projection/ui/projectionMapView.d.ts.map +1 -1
- package/lib/projection/ui/projectionMapView.js +9 -4
- package/lib/projection/ui/projectionMapView.js.map +1 -1
- package/lib/projection/ui/projectionSelectionSentence.d.ts +10 -0
- package/lib/projection/ui/projectionSelectionSentence.d.ts.map +1 -0
- package/lib/projection/ui/projectionSelectionSentence.js +18 -0
- package/lib/projection/ui/projectionSelectionSentence.js.map +1 -0
- package/lib/projection/ui/projectionStateApi.d.ts +47 -0
- package/lib/projection/ui/projectionStateApi.d.ts.map +1 -0
- package/lib/projection/ui/projectionStateApi.js +9 -0
- package/lib/projection/ui/projectionStateApi.js.map +1 -0
- package/lib/projection/ui/projectionTabModels.js +1 -1
- package/lib/projection/ui/projectionTabModels.js.map +1 -1
- package/lib/projection/ui/useProjectionState.d.ts +1 -29
- package/lib/projection/ui/useProjectionState.d.ts.map +1 -1
- package/lib/projection/ui/useProjectionState.js +13 -5
- package/lib/projection/ui/useProjectionState.js.map +1 -1
- package/lib/scatter/core/index.d.ts +1 -0
- package/lib/scatter/core/index.d.ts.map +1 -1
- package/lib/scatter/core/index.js +1 -0
- package/lib/scatter/core/index.js.map +1 -1
- package/lib/scatter/core/pointShape.d.ts +18 -0
- package/lib/scatter/core/pointShape.d.ts.map +1 -0
- package/lib/scatter/core/pointShape.js +70 -0
- package/lib/scatter/core/pointShape.js.map +1 -0
- package/lib/scatter/ui/ScatterPlot.d.ts.map +1 -1
- package/lib/scatter/ui/ScatterPlot.js +3 -2
- package/lib/scatter/ui/ScatterPlot.js.map +1 -1
- package/lib/scatter/ui/ScatterPointLayer.d.ts +14 -1
- package/lib/scatter/ui/ScatterPointLayer.d.ts.map +1 -1
- package/lib/scatter/ui/ScatterPointLayer.js +15 -3
- package/lib/scatter/ui/ScatterPointLayer.js.map +1 -1
- package/lib/scatter/ui/scatterFigureProps.d.ts +13 -0
- package/lib/scatter/ui/scatterFigureProps.d.ts.map +1 -1
- package/lib/scatter/ui/scatterMarkGlyph.d.ts +2 -1
- package/lib/scatter/ui/scatterMarkGlyph.d.ts.map +1 -1
- package/lib/scatter/ui/scatterMarkGlyph.js +7 -1
- package/lib/scatter/ui/scatterMarkGlyph.js.map +1 -1
- package/lib/scatter3d/ui/ScatterCloud.d.ts.map +1 -1
- package/lib/scatter3d/ui/ScatterCloud.js +2 -1
- package/lib/scatter3d/ui/ScatterCloud.js.map +1 -1
- package/package.json +1 -1
- package/src/build/vite/gitHead.ts +17 -2
- package/src/clipboard/ui/ClickToCopy.tsx +190 -0
- package/src/clipboard/ui/CopyButton.tsx +2 -2
- package/src/clipboard/ui/CopyableValue.tsx +11 -6
- package/src/clipboard/ui/index.ts +2 -0
- package/src/ecosystem/core/groups.ts +10 -3
- package/src/ecosystem/core/sites.ts +39 -0
- package/src/ecosystem/core/types.ts +4 -1
- package/src/ecosystem/ui/glyphs.tsx +51 -0
- package/src/error/ui/ErrorFallback.tsx +3 -1
- package/src/overlay/core/index.ts +6 -2
- package/src/overlay/core/overlayMarks.ts +51 -6
- package/src/overlay/ui/OverlayLegendMark.tsx +5 -0
- package/src/pedagogy/ui/ReferenceSectionBlock.tsx +10 -1
- package/src/projection/core/index.ts +11 -3
- package/src/projection/core/projectionCopy.ts +3 -0
- package/src/projection/core/projectionGroupings.ts +174 -0
- package/src/projection/core/projectionOptions.ts +18 -7
- package/src/projection/core/projectionPanelWords.ts +10 -0
- package/src/projection/core/projectionSamples.ts +62 -120
- package/src/projection/core/projectionStrings.ts +12 -1
- package/src/projection/core/resolveProjectionOptions.ts +66 -4
- package/src/projection/ui/ProjectionBar.tsx +4 -2
- package/src/projection/ui/ProjectionGroupingPickers.tsx +91 -0
- package/src/projection/ui/ProjectionMapControls.tsx +29 -32
- package/src/projection/ui/ProjectionMapLegend.tsx +1 -1
- package/src/projection/ui/ProjectionMapMore.tsx +14 -4
- package/src/projection/ui/ProjectionMapTab.tsx +27 -9
- package/src/projection/ui/ProjectionPairsMore.tsx +12 -21
- package/src/projection/ui/ProjectionPairsTab.tsx +5 -2
- package/src/projection/ui/ProjectionPanel.tsx +7 -3
- package/src/projection/ui/ProjectionReadout.tsx +28 -8
- package/src/projection/ui/ProjectionSpaceControls.tsx +20 -27
- package/src/projection/ui/ProjectionSpaceMore.tsx +12 -3
- package/src/projection/ui/ProjectionSpaceTab.tsx +23 -6
- package/src/projection/ui/ProjectionViewer.tsx +1 -0
- package/src/projection/ui/projectionBarReadings.ts +24 -8
- package/src/projection/ui/projectionBarSlots.tsx +10 -9
- package/src/projection/ui/projectionMapChoices.ts +71 -14
- package/src/projection/ui/projectionMapChrome.ts +55 -30
- package/src/projection/ui/projectionMapCorner.ts +67 -0
- package/src/projection/ui/projectionMapModel.ts +20 -59
- package/src/projection/ui/projectionMapView.ts +15 -8
- package/src/projection/ui/projectionSelectionSentence.ts +22 -0
- package/src/projection/ui/projectionStateApi.ts +57 -0
- package/src/projection/ui/projectionTabModels.ts +1 -1
- package/src/projection/ui/useProjectionState.ts +33 -37
- package/src/scatter/core/index.ts +1 -0
- package/src/scatter/core/pointShape.ts +80 -0
- package/src/scatter/ui/ScatterPlot.tsx +4 -1
- package/src/scatter/ui/ScatterPointLayer.tsx +39 -11
- package/src/scatter/ui/scatterFigureProps.ts +13 -0
- package/src/scatter/ui/scatterMarkGlyph.tsx +9 -1
- package/src/scatter3d/ui/ScatterCloud.tsx +3 -0
- package/styles/chrome.css +163 -0
|
@@ -8,9 +8,11 @@ import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
|
|
|
8
8
|
import { OverlaySelect } from '../../overlay/ui/OverlaySelect.tsx';
|
|
9
9
|
import { OverlayToggle } from '../../overlay/ui/OverlayToggle.tsx';
|
|
10
10
|
import type { ScatterSelectionMode } from '../../scatter/core/scatterSelection.ts';
|
|
11
|
+
import { NO_GROUPING } from '../core/projectionOptions.ts';
|
|
11
12
|
import type { ProjectionResult } from '../core/projectionResult.ts';
|
|
12
13
|
import { PROJECTION_TAB_DEFAULTS } from '../core/projectionTabDefaults.ts';
|
|
13
14
|
|
|
15
|
+
import { ProjectionShapePicker } from './ProjectionGroupingPickers.tsx';
|
|
14
16
|
import type { ProjectionMapControlsProps } from './ProjectionMapControls.tsx';
|
|
15
17
|
import { projectionAxisChoices } from './projectionAxisChoices.ts';
|
|
16
18
|
import { projectionSelectModeChoices } from './projectionWordChoices.ts';
|
|
@@ -34,8 +36,8 @@ interface ProjectionMapMoreProps extends ProjectionMapControlsProps {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
|
-
* What the map keeps behind the cog: the axes, the dot size, what a
|
|
38
|
-
* and the three buttons that act rather than change.
|
|
39
|
+
* What the map keeps behind the cog: the axes, the dot size and shape, what a
|
|
40
|
+
* drag does, and the three buttons that act rather than change.
|
|
39
41
|
*
|
|
40
42
|
* Five settings is where a flat list stops being scannable, so they are filed
|
|
41
43
|
* under three headings — the two directions of the picture, the marks drawn in
|
|
@@ -54,13 +56,13 @@ interface ProjectionMapMoreProps extends ProjectionMapControlsProps {
|
|
|
54
56
|
* @returns The panel behind the cog.
|
|
55
57
|
*/
|
|
56
58
|
export function ProjectionMapMore(props: ProjectionMapMoreProps): ReactElement {
|
|
57
|
-
const { result, options, onChange, copy,
|
|
59
|
+
const { result, options, onChange, copy, groupings } = props;
|
|
58
60
|
const { selectedCount = 0, onZoomToSelection } = props;
|
|
59
61
|
const { onResetView, onClearSelection } = props;
|
|
60
62
|
const { action, help, panel, reason, tab } = copy;
|
|
61
63
|
|
|
62
64
|
const nothingPicked = selectedCount === 0;
|
|
63
|
-
const uncoloured =
|
|
65
|
+
const uncoloured = groupings.length === 0 || options.colorBy === NO_GROUPING;
|
|
64
66
|
|
|
65
67
|
return (
|
|
66
68
|
<OverlayPanel
|
|
@@ -124,6 +126,14 @@ export function ProjectionMapMore(props: ProjectionMapMoreProps): ReactElement {
|
|
|
124
126
|
unit="px"
|
|
125
127
|
onChange={(pointRadius) => onChange({ pointRadius })}
|
|
126
128
|
/>
|
|
129
|
+
<ProjectionShapePicker
|
|
130
|
+
label={panel.name.shapeBy}
|
|
131
|
+
options={options}
|
|
132
|
+
onChange={onChange}
|
|
133
|
+
copy={copy}
|
|
134
|
+
groupings={groupings}
|
|
135
|
+
rows={result.scores.rows}
|
|
136
|
+
/>
|
|
127
137
|
<OverlayToggle
|
|
128
138
|
label={panel.name.showGroupMeans}
|
|
129
139
|
help={help.showGroupMeans}
|
|
@@ -7,11 +7,15 @@ import type { ScatterPointOpen } from '../../scatter/ui/scatterFigureProps.ts';
|
|
|
7
7
|
import type { SelectionChange } from '../../scatter/ui/useScatterSelection.ts';
|
|
8
8
|
import type { ProjectionCopy } from '../core/projectionCopy.ts';
|
|
9
9
|
import type { ProjectionOptions } from '../core/projectionOptions.ts';
|
|
10
|
+
import { NO_GROUPING } from '../core/projectionOptions.ts';
|
|
10
11
|
import type {
|
|
11
12
|
ProjectionMarker,
|
|
12
13
|
ProjectionResult,
|
|
13
14
|
} from '../core/projectionResult.ts';
|
|
14
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
ResolvedProjectionGroups,
|
|
17
|
+
ResolvedProjectionShapes,
|
|
18
|
+
} from '../core/projectionSamples.ts';
|
|
15
19
|
|
|
16
20
|
import type { SelectionReport } from './ProjectionMapCaption.tsx';
|
|
17
21
|
import { ProjectionMapCaption } from './ProjectionMapCaption.tsx';
|
|
@@ -25,14 +29,23 @@ import {
|
|
|
25
29
|
projectionMapDomain,
|
|
26
30
|
projectionMapMarkers,
|
|
27
31
|
projectionScatterGroups,
|
|
32
|
+
projectionScatterShapes,
|
|
28
33
|
} from './projectionMapModel.ts';
|
|
29
34
|
|
|
30
35
|
/** What {@link ProjectionMapTab} needs. */
|
|
31
36
|
interface ProjectionMapTabProps {
|
|
32
37
|
/** What the run produced, whatever produced it. */
|
|
33
38
|
result: ProjectionResult;
|
|
34
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* The grouping the dots are coloured by, resolved once by the viewer so every
|
|
41
|
+
* tab colours alike; empty while the colour stands for nothing.
|
|
42
|
+
*/
|
|
35
43
|
groups: ResolvedProjectionGroups;
|
|
44
|
+
/**
|
|
45
|
+
* The grouping the dots are shaped by, resolved once by the viewer.
|
|
46
|
+
* @default null — every dot is a disc
|
|
47
|
+
*/
|
|
48
|
+
shapes?: ResolvedProjectionShapes | null;
|
|
36
49
|
/** What the map is showing, already resolved against `result`. */
|
|
37
50
|
options: ProjectionOptions;
|
|
38
51
|
/** The words the map writes, already merged over the defaults. */
|
|
@@ -44,7 +57,7 @@ interface ProjectionMapTabProps {
|
|
|
44
57
|
* "Sample ID" setting to write beside its dot.
|
|
45
58
|
* @default undefined — the setting has nothing to write and draws nothing
|
|
46
59
|
*/
|
|
47
|
-
|
|
60
|
+
names?: readonly string[];
|
|
48
61
|
/** Width of the figure, in pixels. */
|
|
49
62
|
width: number;
|
|
50
63
|
/** Height of the figure, in pixels. */
|
|
@@ -110,9 +123,10 @@ interface ProjectionMapTabProps {
|
|
|
110
123
|
* The map: one dot per sample, an outline per group, and a key floating in the
|
|
111
124
|
* emptiest corner of the plot.
|
|
112
125
|
*
|
|
113
|
-
* Colour stands for
|
|
114
|
-
*
|
|
115
|
-
* reader came for against the question they have just
|
|
126
|
+
* Colour stands for one grouping and shape, when there is a second, for that
|
|
127
|
+
* one, and a selected dot keeps both and gains a ring — recolouring it would
|
|
128
|
+
* trade the answer the reader came for against the question they have just
|
|
129
|
+
* asked. A sample the
|
|
116
130
|
* model was built from is drawn filled and one placed into the finished model
|
|
117
131
|
* afterwards is drawn hollow, because the second kind can land anywhere and
|
|
118
132
|
* its landing far out is the finding rather than a fault.
|
|
@@ -125,7 +139,8 @@ interface ProjectionMapTabProps {
|
|
|
125
139
|
*/
|
|
126
140
|
export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
|
|
127
141
|
const { result, groups, options, copy, chrome, width, height } = props;
|
|
128
|
-
const {
|
|
142
|
+
const { names, shapes = null, selected } = props;
|
|
143
|
+
const { viewport = null, report = null } = props;
|
|
129
144
|
const { onSelectionChange, onHoverChange, hoverCard } = props;
|
|
130
145
|
const { onPointDoubleClick } = props;
|
|
131
146
|
const { onViewportChange, wheelZoom, touchLasso, testId } = props;
|
|
@@ -147,7 +162,8 @@ export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
|
|
|
147
162
|
[scores, yAxis],
|
|
148
163
|
);
|
|
149
164
|
|
|
150
|
-
const
|
|
165
|
+
const shapeList = useMemo(() => projectionScatterShapes(shapes), [shapes]);
|
|
166
|
+
const colored = colorBy !== NO_GROUPING && groups.entries.length > 0;
|
|
151
167
|
const ellipse = colored ? outlines : null;
|
|
152
168
|
|
|
153
169
|
return (
|
|
@@ -160,11 +176,13 @@ export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
|
|
|
160
176
|
yAxis={{ domain: yDomain, label: projectionAxisTitle(result, yAxis) }}
|
|
161
177
|
groupOf={colored ? groups.groupOf : undefined}
|
|
162
178
|
groups={colored ? projectionScatterGroups(groups) : undefined}
|
|
179
|
+
shapeOf={shapes?.shapeOf}
|
|
180
|
+
shapes={shapeList}
|
|
163
181
|
ellipse={ellipse}
|
|
164
182
|
ellipseMinimumPoints={MINIMUM_OUTLINE_POINTS}
|
|
165
183
|
showGroupMeans={colored && showGroupMeans}
|
|
166
184
|
showGroupLabels={colored && showGroupLabels}
|
|
167
|
-
pointLabels={showIds ?
|
|
185
|
+
pointLabels={showIds ? names : undefined}
|
|
168
186
|
markers={projectionMapMarkers(
|
|
169
187
|
markers ?? NO_MARKERS,
|
|
170
188
|
groups,
|
|
@@ -2,15 +2,12 @@ import type { ReactElement } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { OverlayNumber } from '../../overlay/ui/OverlayNumber.tsx';
|
|
4
4
|
import { OverlayPanel } from '../../overlay/ui/OverlayPanel.tsx';
|
|
5
|
-
import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
|
|
6
5
|
import type { ProjectionCopy } from '../core/projectionCopy.ts';
|
|
7
|
-
import type {
|
|
8
|
-
|
|
9
|
-
ProjectionOptions,
|
|
10
|
-
} from '../core/projectionOptions.ts';
|
|
6
|
+
import type { ProjectionOptions } from '../core/projectionOptions.ts';
|
|
7
|
+
import type { ProjectionGrouping } from '../core/projectionSamples.ts';
|
|
11
8
|
import { PROJECTION_TAB_DEFAULTS } from '../core/projectionTabDefaults.ts';
|
|
12
9
|
|
|
13
|
-
import {
|
|
10
|
+
import { ProjectionColourPicker } from './ProjectionGroupingPickers.tsx';
|
|
14
11
|
import { projectionPairsCeiling } from './projectionPairsCeiling.ts';
|
|
15
12
|
|
|
16
13
|
/** What the grid keeps behind the cog is drawn from. */
|
|
@@ -21,17 +18,12 @@ interface ProjectionPairsMoreProps {
|
|
|
21
18
|
onChange: (patch: Partial<ProjectionOptions>) => void;
|
|
22
19
|
/** The words the bar writes, already merged over the defaults. */
|
|
23
20
|
copy: ProjectionCopy;
|
|
24
|
-
/**
|
|
25
|
-
|
|
21
|
+
/** Every grouping the samples carry, which is what `Colour by` offers. */
|
|
22
|
+
groupings: readonly ProjectionGrouping[];
|
|
26
23
|
/** How many components the run produced, which caps the grid. */
|
|
27
24
|
axisCount: number;
|
|
28
25
|
/** Width of the figure, in pixels, which caps it again. */
|
|
29
26
|
width: number;
|
|
30
|
-
/**
|
|
31
|
-
* Whether the samples carry groups at all.
|
|
32
|
-
* @default false
|
|
33
|
-
*/
|
|
34
|
-
hasGroups?: boolean;
|
|
35
27
|
}
|
|
36
28
|
|
|
37
29
|
/**
|
|
@@ -52,9 +44,9 @@ interface ProjectionPairsMoreProps {
|
|
|
52
44
|
export function ProjectionPairsMore(
|
|
53
45
|
props: ProjectionPairsMoreProps,
|
|
54
46
|
): ReactElement {
|
|
55
|
-
const { options, onChange, copy,
|
|
47
|
+
const { options, onChange, copy, groupings } = props;
|
|
56
48
|
const { axisCount, width } = props;
|
|
57
|
-
const {
|
|
49
|
+
const { help, panel, tab } = copy;
|
|
58
50
|
const ceiling = projectionPairsCeiling(axisCount, width);
|
|
59
51
|
|
|
60
52
|
return (
|
|
@@ -70,13 +62,12 @@ export function ProjectionPairsMore(
|
|
|
70
62
|
max={ceiling.max}
|
|
71
63
|
onChange={(pairCount) => onChange({ pairCount })}
|
|
72
64
|
/>
|
|
73
|
-
<
|
|
65
|
+
<ProjectionColourPicker
|
|
74
66
|
label={panel.name.colorBy}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
onChange={(colorBy) => onChange({ colorBy })}
|
|
67
|
+
options={options}
|
|
68
|
+
onChange={onChange}
|
|
69
|
+
copy={copy}
|
|
70
|
+
groupings={groupings}
|
|
80
71
|
/>
|
|
81
72
|
<OverlayNumber
|
|
82
73
|
label={panel.name.pointRadius}
|
|
@@ -11,7 +11,10 @@ import { fillCopy } from '../core/fillCopy.ts';
|
|
|
11
11
|
import type { ProjectionCopy } from '../core/projectionCopy.ts';
|
|
12
12
|
import { PROJECTION_COPY } from '../core/projectionCopy.ts';
|
|
13
13
|
import type { ProjectionOptions } from '../core/projectionOptions.ts';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_PROJECTION_OPTIONS,
|
|
16
|
+
NO_GROUPING,
|
|
17
|
+
} from '../core/projectionOptions.ts';
|
|
15
18
|
import type { ProjectionResult } from '../core/projectionResult.ts';
|
|
16
19
|
import type { ResolvedProjectionGroups } from '../core/projectionSamples.ts';
|
|
17
20
|
|
|
@@ -96,7 +99,7 @@ export function ProjectionPairsTab(
|
|
|
96
99
|
[groups],
|
|
97
100
|
);
|
|
98
101
|
|
|
99
|
-
const colored = options.colorBy
|
|
102
|
+
const colored = options.colorBy !== NO_GROUPING && inks.length > 0;
|
|
100
103
|
|
|
101
104
|
return (
|
|
102
105
|
<div style={{ minHeight: height }} data-testid={testId}>
|
|
@@ -13,10 +13,10 @@ import { ProjectionSharesTab } from './ProjectionSharesTab.tsx';
|
|
|
13
13
|
import { ProjectionSpaceTab } from './ProjectionSpaceTab.tsx';
|
|
14
14
|
import { ProjectionVariablesTab } from './ProjectionVariablesTab.tsx';
|
|
15
15
|
import type { ProjectionMapView } from './projectionMapView.ts';
|
|
16
|
+
import type { ProjectionStateApi } from './projectionStateApi.ts';
|
|
16
17
|
import type { ProjectionModels } from './projectionTabModels.ts';
|
|
17
18
|
import type { ProjectionVariableTrack } from './projectionVariablesModel.ts';
|
|
18
19
|
import type { ProjectionSampleOpen } from './projectionViewerProps.ts';
|
|
19
|
-
import type { ProjectionStateApi } from './useProjectionState.ts';
|
|
20
20
|
|
|
21
21
|
/** What {@link ProjectionPanel} needs. */
|
|
22
22
|
interface ProjectionPanelProps {
|
|
@@ -172,7 +172,8 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
|
|
|
172
172
|
options={state.options}
|
|
173
173
|
copy={copy}
|
|
174
174
|
chrome={map.spaceChrome}
|
|
175
|
-
|
|
175
|
+
shapes={state.shapes}
|
|
176
|
+
names={samples.labels ?? samples.ids}
|
|
176
177
|
width={width}
|
|
177
178
|
height={height}
|
|
178
179
|
selected={state.selected}
|
|
@@ -192,6 +193,7 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
|
|
|
192
193
|
result={result}
|
|
193
194
|
samples={samples}
|
|
194
195
|
groups={state.groups}
|
|
196
|
+
colorBy={state.options.colorBy}
|
|
195
197
|
xAxis={state.options.xAxis}
|
|
196
198
|
yAxis={state.options.yAxis}
|
|
197
199
|
zAxis={state.options.zAxis}
|
|
@@ -212,7 +214,8 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
|
|
|
212
214
|
options={state.options}
|
|
213
215
|
copy={copy}
|
|
214
216
|
chrome={map.chrome}
|
|
215
|
-
|
|
217
|
+
shapes={state.shapes}
|
|
218
|
+
names={samples.labels ?? samples.ids}
|
|
216
219
|
viewport={map.viewport}
|
|
217
220
|
onViewportChange={map.setViewport}
|
|
218
221
|
wheelZoom={wheelZoom}
|
|
@@ -231,6 +234,7 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
|
|
|
231
234
|
result={result}
|
|
232
235
|
samples={samples}
|
|
233
236
|
groups={state.groups}
|
|
237
|
+
colorBy={state.options.colorBy}
|
|
234
238
|
xAxis={state.options.xAxis}
|
|
235
239
|
yAxis={state.options.yAxis}
|
|
236
240
|
x={anchor.x}
|
|
@@ -19,8 +19,14 @@ interface ProjectionReadoutProps {
|
|
|
19
19
|
result: ProjectionResult;
|
|
20
20
|
/** Who the rows are. */
|
|
21
21
|
samples: ProjectionSamples;
|
|
22
|
-
/** The
|
|
22
|
+
/** The grouping the figure is coloured by, for the colour of the row's group. */
|
|
23
23
|
groups: ResolvedProjectionGroups;
|
|
24
|
+
/**
|
|
25
|
+
* Which grouping colours the figure, so the row of that grouping carries the
|
|
26
|
+
* colour its dot is drawn in.
|
|
27
|
+
* @default undefined — no row carries a colour
|
|
28
|
+
*/
|
|
29
|
+
colorBy?: string;
|
|
24
30
|
/** Which axis is drawn horizontally, from 0. */
|
|
25
31
|
xAxis: number;
|
|
26
32
|
/** Which axis is drawn vertically. */
|
|
@@ -85,6 +91,7 @@ export function ProjectionReadout(props: ProjectionReadoutProps): ReactElement {
|
|
|
85
91
|
result,
|
|
86
92
|
samples,
|
|
87
93
|
groups,
|
|
94
|
+
colorBy,
|
|
88
95
|
xAxis,
|
|
89
96
|
yAxis,
|
|
90
97
|
zAxis,
|
|
@@ -104,8 +111,12 @@ export function ProjectionReadout(props: ProjectionReadoutProps): ReactElement {
|
|
|
104
111
|
[xAxis, yAxis, zAxis],
|
|
105
112
|
);
|
|
106
113
|
const rows = useMemo(
|
|
107
|
-
() =>
|
|
108
|
-
|
|
114
|
+
() =>
|
|
115
|
+
readoutRows(index, result, samples, drawn, formatValue, {
|
|
116
|
+
groups,
|
|
117
|
+
colorBy,
|
|
118
|
+
}),
|
|
119
|
+
[colorBy, drawn, formatValue, groups, index, result, samples],
|
|
109
120
|
);
|
|
110
121
|
|
|
111
122
|
return (
|
|
@@ -114,7 +125,7 @@ export function ProjectionReadout(props: ProjectionReadoutProps): ReactElement {
|
|
|
114
125
|
y={y}
|
|
115
126
|
boxWidth={boxWidth}
|
|
116
127
|
boxHeight={boxHeight}
|
|
117
|
-
title={samples.ids[index] ?? ''}
|
|
128
|
+
title={samples.labels?.[index] ?? samples.ids[index] ?? ''}
|
|
118
129
|
rows={rows}
|
|
119
130
|
maxRows={maxRows}
|
|
120
131
|
pinned={pinned}
|
|
@@ -128,9 +139,9 @@ function readoutRows(
|
|
|
128
139
|
index: number,
|
|
129
140
|
result: ProjectionResult,
|
|
130
141
|
samples: ProjectionSamples,
|
|
131
|
-
groups: ResolvedProjectionGroups,
|
|
132
142
|
drawn: readonly number[],
|
|
133
143
|
formatValue: (value: number) => string,
|
|
144
|
+
coloured: { groups: ResolvedProjectionGroups; colorBy?: string },
|
|
134
145
|
): OverlayReadoutRow[] {
|
|
135
146
|
const rows: OverlayReadoutRow[] = [];
|
|
136
147
|
const { axes, scores } = result;
|
|
@@ -145,9 +156,18 @@ function readoutRows(
|
|
|
145
156
|
});
|
|
146
157
|
}
|
|
147
158
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
// Every grouping is written, the one the dots are coloured by with its
|
|
160
|
+
// colour: a card naming only the colour's group would hide the very
|
|
161
|
+
// grouping the shapes stand for.
|
|
162
|
+
const { groups, colorBy } = coloured;
|
|
163
|
+
for (const grouping of samples.groupings ?? []) {
|
|
164
|
+
const value = grouping.groups[index];
|
|
165
|
+
if (value === undefined) continue;
|
|
166
|
+
const group =
|
|
167
|
+
grouping.id === colorBy
|
|
168
|
+
? groups.entries[groups.groupOf[index] ?? -1]
|
|
169
|
+
: undefined;
|
|
170
|
+
rows.push({ label: grouping.label, value, color: group?.color });
|
|
151
171
|
}
|
|
152
172
|
|
|
153
173
|
if (known && samples.fields !== undefined) {
|
|
@@ -8,11 +8,11 @@ import { OverlayToggle } from '../../overlay/ui/OverlayToggle.tsx';
|
|
|
8
8
|
import { OverlayValueMenu } from '../../overlay/ui/OverlayValueMenu.tsx';
|
|
9
9
|
import type { CloudGesture } from '../../scatter3d/core/cloudGesture.ts';
|
|
10
10
|
import type { ProjectionCopy } from '../core/projectionCopy.ts';
|
|
11
|
-
import type {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from '../core/projectionOptions.ts';
|
|
11
|
+
import type { ProjectionOptions } from '../core/projectionOptions.ts';
|
|
12
|
+
import { NO_GROUPING } from '../core/projectionOptions.ts';
|
|
13
|
+
import type { ProjectionGrouping } from '../core/projectionSamples.ts';
|
|
15
14
|
|
|
15
|
+
import { ProjectionColourPicker } from './ProjectionGroupingPickers.tsx';
|
|
16
16
|
import type { ProjectionReading } from './projectionBarReadings.ts';
|
|
17
17
|
import { projectionChipSettings } from './projectionBarReadings.ts';
|
|
18
18
|
import {
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
ellipseKey,
|
|
21
21
|
ellipseSize,
|
|
22
22
|
} from './projectionEllipse.ts';
|
|
23
|
-
import { projectionColourChoices } from './projectionMapChoices.ts';
|
|
24
23
|
import { projectionCloudGestureChoices } from './projectionWordChoices.ts';
|
|
25
24
|
|
|
26
25
|
/** What the cloud's controls are drawn from, wherever in the bar they sit. */
|
|
@@ -31,14 +30,11 @@ export interface ProjectionSpaceControlsProps {
|
|
|
31
30
|
onChange: (patch: Partial<ProjectionOptions>) => void;
|
|
32
31
|
/** The words the bar writes, already merged over the defaults. */
|
|
33
32
|
copy: ProjectionCopy;
|
|
34
|
-
/** What the set of groups is called. */
|
|
35
|
-
groupLabel: string;
|
|
36
33
|
/**
|
|
37
|
-
*
|
|
34
|
+
* Every grouping the samples carry. Without one the shells stand for
|
|
38
35
|
* nothing, so their control is greyed rather than removed.
|
|
39
|
-
* @default false
|
|
40
36
|
*/
|
|
41
|
-
|
|
37
|
+
groupings: readonly ProjectionGrouping[];
|
|
42
38
|
/**
|
|
43
39
|
* What the settings currently read, built once for the bar and handed down.
|
|
44
40
|
* @default [] — nothing is written, which is what the cog's panel wants
|
|
@@ -71,11 +67,12 @@ export interface ProjectionSpaceControlsProps {
|
|
|
71
67
|
export function ProjectionSpaceControls(
|
|
72
68
|
props: ProjectionSpaceControlsProps,
|
|
73
69
|
): ReactElement {
|
|
74
|
-
const { options, onChange, copy,
|
|
70
|
+
const { options, onChange, copy, groupings } = props;
|
|
75
71
|
const { readings = NO_READINGS, tier = 'full' } = props;
|
|
76
72
|
const { bar, help, outline, reason } = copy;
|
|
77
73
|
|
|
78
|
-
const
|
|
74
|
+
const hasGroups = groupings.length > 0;
|
|
75
|
+
const uncoloured = !hasGroups || options.colorBy === NO_GROUPING;
|
|
79
76
|
const names = (
|
|
80
77
|
<>
|
|
81
78
|
<OverlayToggle
|
|
@@ -109,8 +106,7 @@ export function ProjectionSpaceControls(
|
|
|
109
106
|
options={options}
|
|
110
107
|
onChange={onChange}
|
|
111
108
|
copy={copy}
|
|
112
|
-
|
|
113
|
-
hasGroups={hasGroups}
|
|
109
|
+
groupings={groupings}
|
|
114
110
|
/>
|
|
115
111
|
</OverlayChip>
|
|
116
112
|
{names}
|
|
@@ -151,10 +147,8 @@ interface SpaceSettingsProps {
|
|
|
151
147
|
onChange: (patch: Partial<ProjectionOptions>) => void;
|
|
152
148
|
/** The words the panel writes. */
|
|
153
149
|
copy: ProjectionCopy;
|
|
154
|
-
/**
|
|
155
|
-
|
|
156
|
-
/** Whether the samples carry groups at all. */
|
|
157
|
-
hasGroups: boolean;
|
|
150
|
+
/** Every grouping the samples carry. */
|
|
151
|
+
groupings: readonly ProjectionGrouping[];
|
|
158
152
|
}
|
|
159
153
|
|
|
160
154
|
/**
|
|
@@ -163,8 +157,8 @@ interface SpaceSettingsProps {
|
|
|
163
157
|
* @returns The captioned controls.
|
|
164
158
|
*/
|
|
165
159
|
function SpaceSettings(props: SpaceSettingsProps): ReactElement {
|
|
166
|
-
const { options, onChange, copy,
|
|
167
|
-
const {
|
|
160
|
+
const { options, onChange, copy, groupings } = props;
|
|
161
|
+
const { help, outline } = copy;
|
|
168
162
|
|
|
169
163
|
return (
|
|
170
164
|
<>
|
|
@@ -175,19 +169,18 @@ function SpaceSettings(props: SpaceSettingsProps): ReactElement {
|
|
|
175
169
|
options={projectionCloudGestureChoices(copy)}
|
|
176
170
|
onChange={(cloudGesture) => onChange({ cloudGesture })}
|
|
177
171
|
/>
|
|
178
|
-
<
|
|
172
|
+
<ProjectionColourPicker
|
|
179
173
|
label={help.colorBy.title}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
onChange={(colorBy) => onChange({ colorBy })}
|
|
174
|
+
options={options}
|
|
175
|
+
onChange={onChange}
|
|
176
|
+
copy={copy}
|
|
177
|
+
groupings={groupings}
|
|
185
178
|
/>
|
|
186
179
|
<OverlaySelect
|
|
187
180
|
label={help.ellipse.title}
|
|
188
181
|
help={help.ellipse}
|
|
189
182
|
value={ellipseKey(options.ellipse)}
|
|
190
|
-
disabled={
|
|
183
|
+
disabled={groupings.length === 0 || options.colorBy === NO_GROUPING}
|
|
191
184
|
options={ellipseChoices(options.ellipse, outline, 'space')}
|
|
192
185
|
onChange={(value) => onChange({ ellipse: ellipseSize(value) })}
|
|
193
186
|
/>
|
|
@@ -11,6 +11,7 @@ import type { CloudGesture } from '../../scatter3d/core/cloudGesture.ts';
|
|
|
11
11
|
import type { ProjectionResult } from '../core/projectionResult.ts';
|
|
12
12
|
import { PROJECTION_TAB_DEFAULTS } from '../core/projectionTabDefaults.ts';
|
|
13
13
|
|
|
14
|
+
import { ProjectionShapePicker } from './ProjectionGroupingPickers.tsx';
|
|
14
15
|
import type { ProjectionSpaceControlsProps } from './ProjectionSpaceControls.tsx';
|
|
15
16
|
import { projectionAxisChoices } from './projectionAxisChoices.ts';
|
|
16
17
|
import {
|
|
@@ -35,8 +36,8 @@ interface ProjectionSpaceMoreProps extends ProjectionSpaceControlsProps {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
|
-
* What the cloud keeps behind the cog: its three axes, the dot size
|
|
39
|
-
* the two drags do.
|
|
39
|
+
* What the cloud keeps behind the cog: its three axes, the dot size and shape,
|
|
40
|
+
* and what the two drags do.
|
|
40
41
|
*
|
|
41
42
|
* It is the map's panel with one picker more and one action fewer. There is no
|
|
42
43
|
* "zoom to selection" here, because a box has no frame to draw round a crowd:
|
|
@@ -49,7 +50,7 @@ interface ProjectionSpaceMoreProps extends ProjectionSpaceControlsProps {
|
|
|
49
50
|
export function ProjectionSpaceMore(
|
|
50
51
|
props: ProjectionSpaceMoreProps,
|
|
51
52
|
): ReactElement {
|
|
52
|
-
const { result, options, onChange, copy } = props;
|
|
53
|
+
const { result, options, onChange, copy, groupings } = props;
|
|
53
54
|
const { selectedCount = 0, onResetView, onClearSelection } = props;
|
|
54
55
|
const { action, help, panel, reason, tab } = copy;
|
|
55
56
|
|
|
@@ -122,6 +123,14 @@ export function ProjectionSpaceMore(
|
|
|
122
123
|
unit="px"
|
|
123
124
|
onChange={(pointRadius) => onChange({ pointRadius })}
|
|
124
125
|
/>
|
|
126
|
+
<ProjectionShapePicker
|
|
127
|
+
label={panel.name.shapeBy}
|
|
128
|
+
options={options}
|
|
129
|
+
onChange={onChange}
|
|
130
|
+
copy={copy}
|
|
131
|
+
groupings={groupings}
|
|
132
|
+
rows={result.scores.rows}
|
|
133
|
+
/>
|
|
125
134
|
</OverlayGroup>
|
|
126
135
|
<OverlayGroup label={panel.section.handling}>
|
|
127
136
|
<OverlaySegmented<CloudGesture>
|
|
@@ -7,8 +7,12 @@ import type { OrbitCamera } from '../../scatter3d/core/orbitCamera.ts';
|
|
|
7
7
|
import { ScatterCloud } from '../../scatter3d/ui/ScatterCloud.tsx';
|
|
8
8
|
import type { ProjectionCopy } from '../core/projectionCopy.ts';
|
|
9
9
|
import type { ProjectionOptions } from '../core/projectionOptions.ts';
|
|
10
|
+
import { NO_GROUPING } from '../core/projectionOptions.ts';
|
|
10
11
|
import type { ProjectionResult } from '../core/projectionResult.ts';
|
|
11
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
ResolvedProjectionGroups,
|
|
14
|
+
ResolvedProjectionShapes,
|
|
15
|
+
} from '../core/projectionSamples.ts';
|
|
12
16
|
|
|
13
17
|
import type { SelectionReport } from './ProjectionMapCaption.tsx';
|
|
14
18
|
import { ProjectionMapCaption } from './ProjectionMapCaption.tsx';
|
|
@@ -19,6 +23,7 @@ import {
|
|
|
19
23
|
projectionAxisTitle,
|
|
20
24
|
projectionMapCloud,
|
|
21
25
|
projectionScatterGroups,
|
|
26
|
+
projectionScatterShapes,
|
|
22
27
|
} from './projectionMapModel.ts';
|
|
23
28
|
import { MINIMUM_SHELL_POINTS } from './projectionSpaceModel.ts';
|
|
24
29
|
|
|
@@ -26,8 +31,16 @@ import { MINIMUM_SHELL_POINTS } from './projectionSpaceModel.ts';
|
|
|
26
31
|
interface ProjectionSpaceTabProps {
|
|
27
32
|
/** What the run produced, whatever produced it. */
|
|
28
33
|
result: ProjectionResult;
|
|
29
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* The grouping the dots are coloured by, resolved once by the viewer so every
|
|
36
|
+
* tab colours alike; empty while the colour stands for nothing.
|
|
37
|
+
*/
|
|
30
38
|
groups: ResolvedProjectionGroups;
|
|
39
|
+
/**
|
|
40
|
+
* The grouping the dots are shaped by, resolved once by the viewer.
|
|
41
|
+
* @default null — every dot is a disc
|
|
42
|
+
*/
|
|
43
|
+
shapes?: ResolvedProjectionShapes | null;
|
|
31
44
|
/** What the cloud is showing, already resolved against `result`. */
|
|
32
45
|
options: ProjectionOptions;
|
|
33
46
|
/** The words the cloud writes, already merged over the defaults. */
|
|
@@ -38,7 +51,7 @@ interface ProjectionSpaceTabProps {
|
|
|
38
51
|
* What each sample is called, in the score matrix's row order.
|
|
39
52
|
* @default undefined — the setting has nothing to write and draws nothing
|
|
40
53
|
*/
|
|
41
|
-
|
|
54
|
+
names?: readonly string[];
|
|
42
55
|
/** Width of the figure, in pixels. */
|
|
43
56
|
width: number;
|
|
44
57
|
/** Height of the figure, in pixels. */
|
|
@@ -113,7 +126,8 @@ export function ProjectionSpaceTab(
|
|
|
113
126
|
props: ProjectionSpaceTabProps,
|
|
114
127
|
): ReactElement {
|
|
115
128
|
const { result, groups, options, copy, chrome, width, height } = props;
|
|
116
|
-
const {
|
|
129
|
+
const { names, shapes = null, selected } = props;
|
|
130
|
+
const { report = null, camera, zoom } = props;
|
|
117
131
|
const { onCameraChange, onZoomChange, wheelZoom } = props;
|
|
118
132
|
const { onSelectionChange, onHoverChange, hoverCard, testId } = props;
|
|
119
133
|
const { onPointDoubleClick } = props;
|
|
@@ -131,7 +145,8 @@ export function ProjectionSpaceTab(
|
|
|
131
145
|
[scores, zAxis],
|
|
132
146
|
);
|
|
133
147
|
|
|
134
|
-
const
|
|
148
|
+
const shapeList = useMemo(() => projectionScatterShapes(shapes), [shapes]);
|
|
149
|
+
const colored = colorBy !== NO_GROUPING && groups.entries.length > 0;
|
|
135
150
|
|
|
136
151
|
return (
|
|
137
152
|
<div style={{ position: 'relative' }} data-testid={testId}>
|
|
@@ -146,10 +161,12 @@ export function ProjectionSpaceTab(
|
|
|
146
161
|
zLabel={axisName(result, zAxis)}
|
|
147
162
|
groupOf={colored ? groups.groupOf : undefined}
|
|
148
163
|
groups={colored ? projectionScatterGroups(groups) : undefined}
|
|
164
|
+
shapeOf={shapes?.shapeOf}
|
|
165
|
+
shapes={shapeList}
|
|
149
166
|
ellipsoid={colored ? shells : null}
|
|
150
167
|
ellipsoidMinimumPoints={MINIMUM_SHELL_POINTS}
|
|
151
168
|
showGroupLabels={colored && showGroupLabels}
|
|
152
|
-
pointLabels={showIds ?
|
|
169
|
+
pointLabels={showIds ? names : undefined}
|
|
153
170
|
pointRadius={pointRadius}
|
|
154
171
|
outlinedFrom={fittedCount}
|
|
155
172
|
selected={selected}
|