doom-design-system 0.5.0 → 0.6.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/dist/components/Accordion/Accordion.module.css +121 -124
- package/dist/components/ActionRow/ActionRow.module.css +25 -24
- package/dist/components/Alert/Alert.module.css +74 -76
- package/dist/components/Avatar/Avatar.module.css +66 -66
- package/dist/components/Badge/Badge.module.css +50 -48
- package/dist/components/Breadcrumbs/Breadcrumbs.module.css +32 -33
- package/dist/components/Button/Button.d.ts +2 -2
- package/dist/components/Button/Button.js +1 -1
- package/dist/components/Button/Button.module.css +150 -152
- package/dist/components/Card/Card.module.css +37 -39
- package/dist/components/Chart/Chart.module.css +213 -245
- package/dist/components/Chart/behaviors/DraggablePuck.d.ts +36 -0
- package/dist/components/Chart/behaviors/DraggablePuck.js +94 -0
- package/dist/components/Chart/behaviors/Markers.js +6 -4
- package/dist/components/Chart/behaviors/SelectionUpdate.js +2 -4
- package/dist/components/Chart/behaviors/index.d.ts +1 -1
- package/dist/components/Chart/behaviors/index.js +1 -1
- package/dist/components/Chart/engine/CoordinateSystem.d.ts +59 -0
- package/dist/components/Chart/engine/CoordinateSystem.js +126 -0
- package/dist/components/Chart/engine/Engine.d.ts +102 -0
- package/dist/components/Chart/engine/Engine.js +226 -0
- package/dist/components/Chart/engine/Scheduler.d.ts +59 -0
- package/dist/components/Chart/engine/Scheduler.js +139 -0
- package/dist/components/Chart/engine/SpatialMap.d.ts +114 -0
- package/dist/components/Chart/engine/SpatialMap.js +270 -0
- package/dist/components/Chart/engine/index.d.ts +13 -0
- package/dist/components/Chart/engine/index.js +9 -0
- package/dist/components/Chart/engine/types.d.ts +137 -0
- package/dist/components/Chart/engine/types.js +47 -0
- package/dist/components/Chart/hooks/useEngine.d.ts +43 -0
- package/dist/components/Chart/hooks/useEngine.js +128 -0
- package/dist/components/Chart/sensors/DataHoverSensor/DataHoverSensor.d.ts +17 -19
- package/dist/components/Chart/sensors/DataHoverSensor/DataHoverSensor.js +38 -51
- package/dist/components/Chart/sensors/DragSensor/DragSensor.d.ts +38 -0
- package/dist/components/Chart/sensors/DragSensor/DragSensor.js +105 -0
- package/dist/components/Chart/sensors/DragSensor/index.d.ts +2 -0
- package/dist/components/Chart/sensors/DragSensor/index.js +1 -0
- package/dist/components/Chart/sensors/{KeyboardSensor.d.ts → KeyboardSensor/KeyboardSensor.d.ts} +1 -1
- package/dist/components/Chart/sensors/KeyboardSensor/KeyboardSensor.js +86 -0
- package/dist/components/Chart/sensors/KeyboardSensor/index.d.ts +1 -0
- package/dist/components/Chart/sensors/KeyboardSensor/index.js +1 -0
- package/dist/components/Chart/sensors/{SelectionSensor.d.ts → SelectionSensor/SelectionSensor.d.ts} +2 -2
- package/dist/components/Chart/sensors/SelectionSensor/SelectionSensor.js +39 -0
- package/dist/components/Chart/sensors/SelectionSensor/index.d.ts +1 -0
- package/dist/components/Chart/sensors/SelectionSensor/index.js +1 -0
- package/dist/components/Chart/sensors/SensorManager/SensorManager.js +36 -41
- package/dist/components/Chart/sensors/index.d.ts +1 -0
- package/dist/components/Chart/sensors/index.js +3 -2
- package/dist/components/Chart/sensors/utils/search.d.ts +1 -1
- package/dist/components/Chart/sensors/utils/search.js +25 -4
- package/dist/components/Chart/state/store/chart.store.js +18 -0
- package/dist/components/Chart/state/store/slices/series.slice.d.ts +1 -0
- package/dist/components/Chart/state/store/slices/series.slice.js +3 -2
- package/dist/components/Chart/subcomponents/Axis/Axis.module.css +32 -33
- package/dist/components/Chart/subcomponents/BarSeries/BarSeries.js +6 -1
- package/dist/components/Chart/subcomponents/BarSeries/BarSeries.module.css +11 -9
- package/dist/components/Chart/subcomponents/Cursor/Cursor.js +8 -1
- package/dist/components/Chart/subcomponents/Cursor/Cursor.module.css +14 -13
- package/dist/components/Chart/subcomponents/CustomSeries/CustomSeries.js +4 -0
- package/dist/components/Chart/subcomponents/CustomSeries/CustomSeries.module.css +5 -3
- package/dist/components/Chart/subcomponents/Footer/Footer.module.css +5 -3
- package/dist/components/Chart/subcomponents/Grid/Grid.module.css +12 -11
- package/dist/components/Chart/subcomponents/Header/Header.module.css +8 -7
- package/dist/components/Chart/subcomponents/InteractionLayer/InteractionLayer.d.ts +4 -4
- package/dist/components/Chart/subcomponents/InteractionLayer/InteractionLayer.js +39 -76
- package/dist/components/Chart/subcomponents/Legend/Legend.module.css +30 -32
- package/dist/components/Chart/subcomponents/LineSeries/LineSeries.js +9 -3
- package/dist/components/Chart/subcomponents/LineSeries/LineSeries.module.css +21 -21
- package/dist/components/Chart/subcomponents/Root/Root.js +113 -7
- package/dist/components/Chart/subcomponents/Root/Root.module.css +70 -82
- package/dist/components/Chart/subcomponents/ScatterSeries/ScatterSeries.js +6 -1
- package/dist/components/Chart/subcomponents/ScatterSeries/ScatterSeries.module.css +7 -5
- package/dist/components/Chart/subcomponents/Series/Series.module.css +118 -128
- package/dist/components/Chart/subcomponents/SeriesPoint/SeriesPoint.module.css +10 -8
- package/dist/components/Chart/subcomponents/Tooltip/Tooltip.js +2 -3
- package/dist/components/Chart/subcomponents/Tooltip/Tooltip.module.css +52 -67
- package/dist/components/Chart/types/context.d.ts +9 -0
- package/dist/components/Chart/types/events.d.ts +5 -7
- package/dist/components/Chart/types/interaction.d.ts +24 -2
- package/dist/components/Chart/types/interaction.js +1 -0
- package/dist/components/Checkbox/Checkbox.module.css +57 -59
- package/dist/components/Chip/Chip.module.css +105 -115
- package/dist/components/Combobox/Combobox.d.ts +2 -1
- package/dist/components/Combobox/Combobox.js +2 -2
- package/dist/components/Combobox/Combobox.module.css +233 -210
- package/dist/components/CopyButton/CopyButton.module.css +84 -90
- package/dist/components/Drawer/Drawer.module.css +126 -145
- package/dist/components/Dropdown/Dropdown.d.ts +3 -1
- package/dist/components/Dropdown/Dropdown.js +3 -3
- package/dist/components/Dropdown/Dropdown.module.css +52 -32
- package/dist/components/FileUpload/FileUpload.js +24 -0
- package/dist/components/FileUpload/FileUpload.module.css +295 -313
- package/dist/components/Form/Form.module.css +35 -39
- package/dist/components/Image/Image.module.css +53 -54
- package/dist/components/Input/Input.d.ts +4 -2
- package/dist/components/Input/Input.js +2 -2
- package/dist/components/Input/Input.module.css +135 -119
- package/dist/components/Label/Label.module.css +17 -15
- package/dist/components/Layout/Layout.module.css +95 -111
- package/dist/components/Link/Link.module.css +67 -65
- package/dist/components/Modal/Modal.module.css +112 -132
- package/dist/components/Page/Page.module.css +21 -21
- package/dist/components/Pagination/Pagination.module.css +56 -56
- package/dist/components/Popover/Popover.module.css +17 -16
- package/dist/components/ProgressBar/ProgressBar.module.css +36 -37
- package/dist/components/RadioGroup/RadioGroup.module.css +74 -77
- package/dist/components/Select/Select.d.ts +2 -1
- package/dist/components/Select/Select.js +2 -2
- package/dist/components/Select/Select.module.css +133 -98
- package/dist/components/Sheet/Sheet.module.css +134 -154
- package/dist/components/Sidebar/Sidebar.module.css +72 -74
- package/dist/components/Sidebar/subcomponents/Footer/Footer.module.css +7 -5
- package/dist/components/Sidebar/subcomponents/Group/Group.module.css +80 -85
- package/dist/components/Sidebar/subcomponents/Header/Header.module.css +12 -10
- package/dist/components/Sidebar/subcomponents/Item/Item.module.css +54 -55
- package/dist/components/Sidebar/subcomponents/MobileOverlay/MobileOverlay.module.css +38 -38
- package/dist/components/Sidebar/subcomponents/MobileTrigger/MobileTrigger.module.css +5 -3
- package/dist/components/Sidebar/subcomponents/Nav/Nav.module.css +13 -11
- package/dist/components/Sidebar/subcomponents/Rail/Rail.module.css +62 -63
- package/dist/components/Sidebar/subcomponents/Section/Section.module.css +86 -91
- package/dist/components/Skeleton/Skeleton.module.css +28 -26
- package/dist/components/Slat/Slat.module.css +93 -94
- package/dist/components/Slider/Slider.module.css +116 -121
- package/dist/components/Spinner/Spinner.module.css +28 -27
- package/dist/components/SplitButton/SplitButton.d.ts +3 -1
- package/dist/components/SplitButton/SplitButton.js +2 -2
- package/dist/components/SplitButton/SplitButton.module.css +104 -87
- package/dist/components/Switch/Switch.module.css +64 -63
- package/dist/components/Table/FilterBuilder/FilterBuilder.module.css +36 -36
- package/dist/components/Table/FilterBuilder/FilterConditionRow.js +1 -1
- package/dist/components/Table/FilterBuilder/FilterConditionRow.module.css +21 -22
- package/dist/components/Table/FilterBuilder/FilterGroup.js +4 -4
- package/dist/components/Table/FilterBuilder/FilterGroup.module.css +355 -389
- package/dist/components/Table/FilterBuilder/FilterSheet.module.css +68 -71
- package/dist/components/Table/Table.d.ts +4 -2
- package/dist/components/Table/Table.js +50 -13
- package/dist/components/Table/Table.module.css +210 -188
- package/dist/components/Table/TableHeaderFilter.js +1 -1
- package/dist/components/Table/TableHeaderFilter.module.css +51 -57
- package/dist/components/Tabs/Tabs.module.css +79 -80
- package/dist/components/Text/Text.module.css +108 -131
- package/dist/components/Textarea/Textarea.d.ts +3 -1
- package/dist/components/Textarea/Textarea.js +2 -2
- package/dist/components/Textarea/Textarea.module.css +114 -94
- package/dist/components/Toast/Toast.module.css +82 -82
- package/dist/components/Tooltip/Tooltip.module.css +17 -16
- package/dist/styles/globals.css +1677 -1691
- package/dist/styles/palettes.d.ts +0 -5
- package/dist/styles/palettes.js +0 -8
- package/dist/styles/themes/definitions.d.ts +0 -8
- package/dist/styles/themes/definitions.js +117 -5
- package/dist/styles/types.d.ts +2 -0
- package/dist/styles/types.js +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/.agent/skills/doom/a2ui/a2ui-examples.md +0 -289
- package/.agent/skills/doom/a2ui/a2ui-principles.md +0 -49
- package/.agent/skills/doom/a2ui/a2ui-protocol.md +0 -191
- package/.agent/skills/doom/components/a2ui.md +0 -46
- package/.agent/skills/doom/components/accordion.md +0 -44
- package/.agent/skills/doom/components/actionrow.md +0 -33
- package/.agent/skills/doom/components/alert.md +0 -35
- package/.agent/skills/doom/components/avatar.md +0 -36
- package/.agent/skills/doom/components/badge.md +0 -29
- package/.agent/skills/doom/components/breadcrumbs.md +0 -33
- package/.agent/skills/doom/components/button.md +0 -43
- package/.agent/skills/doom/components/card.md +0 -41
- package/.agent/skills/doom/components/chart.md +0 -106
- package/.agent/skills/doom/components/checkbox.md +0 -38
- package/.agent/skills/doom/components/chip.md +0 -35
- package/.agent/skills/doom/components/combobox.md +0 -50
- package/.agent/skills/doom/components/copybutton.md +0 -41
- package/.agent/skills/doom/components/drawer.md +0 -69
- package/.agent/skills/doom/components/dropdown.md +0 -33
- package/.agent/skills/doom/components/fileupload.md +0 -49
- package/.agent/skills/doom/components/form.md +0 -55
- package/.agent/skills/doom/components/icon.md +0 -47
- package/.agent/skills/doom/components/image.md +0 -48
- package/.agent/skills/doom/components/input.md +0 -54
- package/.agent/skills/doom/components/label.md +0 -32
- package/.agent/skills/doom/components/layout.md +0 -92
- package/.agent/skills/doom/components/link.md +0 -39
- package/.agent/skills/doom/components/modal.md +0 -71
- package/.agent/skills/doom/components/page.md +0 -41
- package/.agent/skills/doom/components/pagination.md +0 -32
- package/.agent/skills/doom/components/popover.md +0 -45
- package/.agent/skills/doom/components/progressbar.md +0 -37
- package/.agent/skills/doom/components/radiogroup.md +0 -45
- package/.agent/skills/doom/components/select.md +0 -43
- package/.agent/skills/doom/components/sheet.md +0 -71
- package/.agent/skills/doom/components/sidebar.md +0 -92
- package/.agent/skills/doom/components/skeleton.md +0 -35
- package/.agent/skills/doom/components/slat.md +0 -46
- package/.agent/skills/doom/components/slider.md +0 -51
- package/.agent/skills/doom/components/spinner.md +0 -34
- package/.agent/skills/doom/components/splitbutton.md +0 -35
- package/.agent/skills/doom/components/switch.md +0 -40
- package/.agent/skills/doom/components/table.md +0 -82
- package/.agent/skills/doom/components/tabs.md +0 -65
- package/.agent/skills/doom/components/text.md +0 -42
- package/.agent/skills/doom/components/textarea.md +0 -46
- package/.agent/skills/doom/components/toast.md +0 -59
- package/.agent/skills/doom/components/tooltip.md +0 -35
- package/.agent/skills/doom/index.md +0 -167
- package/.agent/skills/doom/styles/aesthetic.md +0 -151
- package/.agent/skills/doom/styles/css-variables.md +0 -80
- package/.agent/skills/doom/styles/mixins.md +0 -97
- package/.agent/skills/doom/styles/tokens.md +0 -129
- package/.agent/skills/doom/styles/utilities.md +0 -84
- package/dist/components/Chart/sensors/KeyboardSensor.js +0 -82
- package/dist/components/Chart/sensors/SelectionSensor.js +0 -41
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface ContainerStyle {
|
|
2
|
+
borderLeft: number;
|
|
3
|
+
borderTop: number;
|
|
4
|
+
paddingLeft: number;
|
|
5
|
+
paddingTop: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PlotBounds {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ChartCoordinates {
|
|
14
|
+
chartX: number;
|
|
15
|
+
chartY: number;
|
|
16
|
+
isWithinPlot: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* CoordinateSystem
|
|
20
|
+
*
|
|
21
|
+
* Handles the complexity of mapping screen coordinates (ClientX/Y)
|
|
22
|
+
* to Chart coordinates (PlotX/Y), accounting for:
|
|
23
|
+
* - Container position (getBoundingClientRect)
|
|
24
|
+
* - CSS Borders and Padding
|
|
25
|
+
* - Layout offsets (e.g. Headers pushing the plot down)
|
|
26
|
+
*/
|
|
27
|
+
export declare class CoordinateSystem {
|
|
28
|
+
private containerRect;
|
|
29
|
+
private containerStyle;
|
|
30
|
+
private plotOffset;
|
|
31
|
+
private plotBounds;
|
|
32
|
+
/**
|
|
33
|
+
* Set the container element and its bounds.
|
|
34
|
+
* Call this on mount and when the container resizes.
|
|
35
|
+
*/
|
|
36
|
+
setContainer(element: Element | null, plotElement?: Element | null, plotBounds?: PlotBounds): void;
|
|
37
|
+
/**
|
|
38
|
+
* Update the container bounds explicitly (e.g. from ResizeObserver).
|
|
39
|
+
*/
|
|
40
|
+
updateBounds(rect: DOMRect, plotBounds?: PlotBounds): void;
|
|
41
|
+
getContainerRect(): DOMRect | null;
|
|
42
|
+
getContainerStyle(): ContainerStyle;
|
|
43
|
+
getPlotOffset(): {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
};
|
|
47
|
+
getPlotBounds(): PlotBounds | null;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a pointer event to container-relative (padding-box) coordinates.
|
|
50
|
+
*/
|
|
51
|
+
resolvePointerCoordinates(clientX: number, clientY: number): {
|
|
52
|
+
x: number;
|
|
53
|
+
y: number;
|
|
54
|
+
} | null;
|
|
55
|
+
/**
|
|
56
|
+
* Calculate coordinates relative to the plot area.
|
|
57
|
+
*/
|
|
58
|
+
resolveChartCoordinates(containerX: number, containerY: number): ChartCoordinates;
|
|
59
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoordinateSystem
|
|
3
|
+
*
|
|
4
|
+
* Handles the complexity of mapping screen coordinates (ClientX/Y)
|
|
5
|
+
* to Chart coordinates (PlotX/Y), accounting for:
|
|
6
|
+
* - Container position (getBoundingClientRect)
|
|
7
|
+
* - CSS Borders and Padding
|
|
8
|
+
* - Layout offsets (e.g. Headers pushing the plot down)
|
|
9
|
+
*/
|
|
10
|
+
export class CoordinateSystem {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.containerRect = null;
|
|
13
|
+
this.containerStyle = {
|
|
14
|
+
borderLeft: 0,
|
|
15
|
+
borderTop: 0,
|
|
16
|
+
paddingLeft: 0,
|
|
17
|
+
paddingTop: 0,
|
|
18
|
+
};
|
|
19
|
+
this.plotOffset = { x: 0, y: 0 };
|
|
20
|
+
this.plotBounds = null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Set the container element and its bounds.
|
|
24
|
+
* Call this on mount and when the container resizes.
|
|
25
|
+
*/
|
|
26
|
+
setContainer(element, plotElement = null, plotBounds) {
|
|
27
|
+
if (element) {
|
|
28
|
+
this.containerRect = element.getBoundingClientRect();
|
|
29
|
+
const style = window.getComputedStyle(element);
|
|
30
|
+
this.containerStyle = {
|
|
31
|
+
borderLeft: parseFloat(style.borderLeftWidth) || 0,
|
|
32
|
+
borderTop: parseFloat(style.borderTopWidth) || 0,
|
|
33
|
+
paddingLeft: parseFloat(style.paddingLeft) || 0,
|
|
34
|
+
paddingTop: parseFloat(style.paddingTop) || 0,
|
|
35
|
+
};
|
|
36
|
+
// Calculate plot offset if plotElement is provided
|
|
37
|
+
if (plotElement) {
|
|
38
|
+
const plotRect = plotElement.getBoundingClientRect();
|
|
39
|
+
this.plotOffset = {
|
|
40
|
+
x: plotRect.left -
|
|
41
|
+
this.containerRect.left -
|
|
42
|
+
this.containerStyle.borderLeft,
|
|
43
|
+
y: plotRect.top -
|
|
44
|
+
this.containerRect.top -
|
|
45
|
+
this.containerStyle.borderTop,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Fallback to padding
|
|
50
|
+
this.plotOffset = {
|
|
51
|
+
x: this.containerStyle.paddingLeft,
|
|
52
|
+
y: this.containerStyle.paddingTop,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.containerRect = null;
|
|
58
|
+
this.containerStyle = {
|
|
59
|
+
borderLeft: 0,
|
|
60
|
+
borderTop: 0,
|
|
61
|
+
paddingLeft: 0,
|
|
62
|
+
paddingTop: 0,
|
|
63
|
+
};
|
|
64
|
+
this.plotOffset = { x: 0, y: 0 };
|
|
65
|
+
}
|
|
66
|
+
if (plotBounds) {
|
|
67
|
+
this.plotBounds = plotBounds;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Update the container bounds explicitly (e.g. from ResizeObserver).
|
|
72
|
+
*/
|
|
73
|
+
updateBounds(rect, plotBounds) {
|
|
74
|
+
this.containerRect = rect;
|
|
75
|
+
if (plotBounds) {
|
|
76
|
+
this.plotBounds = plotBounds;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
getContainerRect() {
|
|
80
|
+
return this.containerRect;
|
|
81
|
+
}
|
|
82
|
+
getContainerStyle() {
|
|
83
|
+
return this.containerStyle;
|
|
84
|
+
}
|
|
85
|
+
getPlotOffset() {
|
|
86
|
+
return this.plotOffset;
|
|
87
|
+
}
|
|
88
|
+
getPlotBounds() {
|
|
89
|
+
return this.plotBounds;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a pointer event to container-relative (padding-box) coordinates.
|
|
93
|
+
*/
|
|
94
|
+
resolvePointerCoordinates(clientX, clientY) {
|
|
95
|
+
if (!this.containerRect) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
x: clientX - this.containerRect.left - this.containerStyle.borderLeft,
|
|
100
|
+
y: clientY - this.containerRect.top - this.containerStyle.borderTop,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Calculate coordinates relative to the plot area.
|
|
105
|
+
*/
|
|
106
|
+
resolveChartCoordinates(containerX, containerY) {
|
|
107
|
+
// If we have plot bounds (from d3 scales/margin), use them for plotting
|
|
108
|
+
// Note: containerX/Y here are expected to be relative to the Plot Offset already?
|
|
109
|
+
// Wait, the previous implementation passed "searchX/Y" which were (signal.x - plotOffset).
|
|
110
|
+
// Let's keep it consistent.
|
|
111
|
+
if (!this.plotBounds) {
|
|
112
|
+
// If no plot bounds defined, assume full container? OR just return relative coords
|
|
113
|
+
return { chartX: containerX, chartY: containerY, isWithinPlot: true };
|
|
114
|
+
}
|
|
115
|
+
// plotBounds.x/y are usually the margin.left/top
|
|
116
|
+
// If containerX is already relative to the visual plot origin (wrapper),
|
|
117
|
+
// and margin is inside that wrapper (SVG g transform), then we need to subtract margin.
|
|
118
|
+
const chartX = containerX - this.plotBounds.x;
|
|
119
|
+
const chartY = containerY - this.plotBounds.y;
|
|
120
|
+
const isWithinPlot = chartX >= 0 &&
|
|
121
|
+
chartX <= this.plotBounds.width &&
|
|
122
|
+
chartY >= 0 &&
|
|
123
|
+
chartY <= this.plotBounds.height;
|
|
124
|
+
return { chartX, chartY, isWithinPlot };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine
|
|
3
|
+
*
|
|
4
|
+
* The central brain of the Chart interaction system.
|
|
5
|
+
* Receives InputSignals, queries the SpatialIndex, and dispatches to the Scheduler.
|
|
6
|
+
*/
|
|
7
|
+
import { TaskHandler } from "./Scheduler";
|
|
8
|
+
import { IndexedPoint, SpatialMapOptions } from "./SpatialMap";
|
|
9
|
+
import { InputAction, InputSignal } from "./types";
|
|
10
|
+
export interface EngineOptions extends SpatialMapOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Called when an engine event is ready for dispatch.
|
|
13
|
+
* In the full system, this connects to the EventBus.
|
|
14
|
+
*/
|
|
15
|
+
onEvent?: TaskHandler;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The Engine is the core of the Hyper-Engine architecture.
|
|
19
|
+
*
|
|
20
|
+
* Responsibilities:
|
|
21
|
+
* 1. Receive InputSignals from the InteractionLayer (or remote sources)
|
|
22
|
+
* 2. Normalize coordinates (client -> container)
|
|
23
|
+
* 3. Query the SpatialMap to find candidates
|
|
24
|
+
* 4. Schedule events based on priority
|
|
25
|
+
* 5. Dispatch to sensors via the configured handler
|
|
26
|
+
*/
|
|
27
|
+
export declare class Engine<T = unknown> {
|
|
28
|
+
private spatialMap;
|
|
29
|
+
private scheduler;
|
|
30
|
+
private coords;
|
|
31
|
+
private disposed;
|
|
32
|
+
constructor(options?: EngineOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Set the container element and its bounds.
|
|
35
|
+
* Call this on mount and when the container resizes.
|
|
36
|
+
*/
|
|
37
|
+
setContainer(element: Element | null, plotElement?: Element | null, plotBounds?: {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
}): void;
|
|
43
|
+
/**
|
|
44
|
+
* Update the container bounds without changing the element reference.
|
|
45
|
+
* Useful for resize handling.
|
|
46
|
+
*/
|
|
47
|
+
updateBounds(rect: DOMRect, plotBounds?: {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}): void;
|
|
53
|
+
/**
|
|
54
|
+
* Update the spatial index with new data points.
|
|
55
|
+
*/
|
|
56
|
+
updateData(points: IndexedPoint<T>[]): void;
|
|
57
|
+
/**
|
|
58
|
+
* Set the event handler.
|
|
59
|
+
*/
|
|
60
|
+
setHandler(handler: TaskHandler<T>): void;
|
|
61
|
+
/**
|
|
62
|
+
* Clean up all resources.
|
|
63
|
+
*/
|
|
64
|
+
dispose(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Process an InputSignal.
|
|
67
|
+
* This is the main entry point for all user interactions.
|
|
68
|
+
*
|
|
69
|
+
* @param signal - The normalized input signal
|
|
70
|
+
*/
|
|
71
|
+
input(signal: InputSignal): void;
|
|
72
|
+
/**
|
|
73
|
+
* Create an InputSignal from a native PointerEvent.
|
|
74
|
+
* Convenience method for the InteractionLayer.
|
|
75
|
+
*/
|
|
76
|
+
createSignal(event: PointerEvent | MouseEvent | TouchEvent, action: InputAction, userId?: string): InputSignal | null;
|
|
77
|
+
/**
|
|
78
|
+
* Create an InputSignal from a KeyboardEvent.
|
|
79
|
+
*/
|
|
80
|
+
createKeySignal(event: KeyboardEvent, userId?: string): InputSignal;
|
|
81
|
+
/**
|
|
82
|
+
* Determine the scheduling priority for an action.
|
|
83
|
+
*/
|
|
84
|
+
private determinePriority;
|
|
85
|
+
/**
|
|
86
|
+
* Get the current container bounds.
|
|
87
|
+
*/
|
|
88
|
+
getContainerRect(): DOMRect | null;
|
|
89
|
+
/**
|
|
90
|
+
* Get the current plot bounds.
|
|
91
|
+
*/
|
|
92
|
+
getPlotBounds(): {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
width: number;
|
|
96
|
+
height: number;
|
|
97
|
+
} | null;
|
|
98
|
+
/**
|
|
99
|
+
* Check if the engine has been disposed.
|
|
100
|
+
*/
|
|
101
|
+
isDisposed(): boolean;
|
|
102
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine
|
|
3
|
+
*
|
|
4
|
+
* The central brain of the Chart interaction system.
|
|
5
|
+
* Receives InputSignals, queries the SpatialIndex, and dispatches to the Scheduler.
|
|
6
|
+
*/
|
|
7
|
+
import { CoordinateSystem } from "./CoordinateSystem.js";
|
|
8
|
+
import { Scheduler } from "./Scheduler.js";
|
|
9
|
+
import { SpatialMap } from "./SpatialMap.js";
|
|
10
|
+
import { InputAction, InputSource, TaskPriority, } from "./types.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// ENGINE CLASS
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* The Engine is the core of the Hyper-Engine architecture.
|
|
16
|
+
*
|
|
17
|
+
* Responsibilities:
|
|
18
|
+
* 1. Receive InputSignals from the InteractionLayer (or remote sources)
|
|
19
|
+
* 2. Normalize coordinates (client -> container)
|
|
20
|
+
* 3. Query the SpatialMap to find candidates
|
|
21
|
+
* 4. Schedule events based on priority
|
|
22
|
+
* 5. Dispatch to sensors via the configured handler
|
|
23
|
+
*/
|
|
24
|
+
export class Engine {
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
this.disposed = false;
|
|
27
|
+
this.spatialMap = new SpatialMap(options);
|
|
28
|
+
this.scheduler = new Scheduler();
|
|
29
|
+
this.coords = new CoordinateSystem();
|
|
30
|
+
if (options.onEvent) {
|
|
31
|
+
this.scheduler.setHandler(options.onEvent);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ===========================================================================
|
|
35
|
+
// LIFECYCLE
|
|
36
|
+
// ===========================================================================
|
|
37
|
+
/**
|
|
38
|
+
* Set the container element and its bounds.
|
|
39
|
+
* Call this on mount and when the container resizes.
|
|
40
|
+
*/
|
|
41
|
+
setContainer(element, plotElement = null, plotBounds) {
|
|
42
|
+
if (element) {
|
|
43
|
+
this.spatialMap.setContainer(element);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.spatialMap.setContainer(null);
|
|
47
|
+
}
|
|
48
|
+
this.coords.setContainer(element, plotElement, plotBounds);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Update the container bounds without changing the element reference.
|
|
52
|
+
* Useful for resize handling.
|
|
53
|
+
*/
|
|
54
|
+
updateBounds(rect, plotBounds) {
|
|
55
|
+
this.coords.updateBounds(rect, plotBounds);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Update the spatial index with new data points.
|
|
59
|
+
*/
|
|
60
|
+
updateData(points) {
|
|
61
|
+
this.spatialMap.updateIndex(points);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Set the event handler.
|
|
65
|
+
*/
|
|
66
|
+
setHandler(handler) {
|
|
67
|
+
this.scheduler.setHandler(handler);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clean up all resources.
|
|
71
|
+
*/
|
|
72
|
+
dispose() {
|
|
73
|
+
if (this.disposed) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.disposed = true;
|
|
77
|
+
this.scheduler.dispose();
|
|
78
|
+
this.spatialMap.clear();
|
|
79
|
+
}
|
|
80
|
+
// ===========================================================================
|
|
81
|
+
// INPUT PROCESSING
|
|
82
|
+
// ===========================================================================
|
|
83
|
+
/**
|
|
84
|
+
* Process an InputSignal.
|
|
85
|
+
* This is the main entry point for all user interactions.
|
|
86
|
+
*
|
|
87
|
+
* @param signal - The normalized input signal
|
|
88
|
+
*/
|
|
89
|
+
input(signal) {
|
|
90
|
+
if (this.disposed) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const plotOffset = this.coords.getPlotOffset();
|
|
94
|
+
const searchX = signal.x - plotOffset.x;
|
|
95
|
+
const searchY = signal.y - plotOffset.y;
|
|
96
|
+
const candidates = this.spatialMap.find(searchX, searchY, {
|
|
97
|
+
x: signal.x,
|
|
98
|
+
y: signal.y,
|
|
99
|
+
});
|
|
100
|
+
const { chartX, chartY, isWithinPlot } = this.coords.resolveChartCoordinates(searchX, searchY);
|
|
101
|
+
const primaryCandidate = candidates[0];
|
|
102
|
+
const sliceCandidates = primaryCandidate
|
|
103
|
+
? this.spatialMap.findAllAtX(primaryCandidate.coordinate.x)
|
|
104
|
+
: [];
|
|
105
|
+
const event = {
|
|
106
|
+
signal,
|
|
107
|
+
candidates,
|
|
108
|
+
primaryCandidate,
|
|
109
|
+
sliceCandidates,
|
|
110
|
+
chartX,
|
|
111
|
+
chartY,
|
|
112
|
+
isWithinPlot,
|
|
113
|
+
};
|
|
114
|
+
const priority = this.determinePriority(signal.action);
|
|
115
|
+
this.scheduler.schedule(priority, event);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create an InputSignal from a native PointerEvent.
|
|
119
|
+
* Convenience method for the InteractionLayer.
|
|
120
|
+
*/
|
|
121
|
+
createSignal(event, action, userId = "local") {
|
|
122
|
+
let clientX;
|
|
123
|
+
let clientY;
|
|
124
|
+
if ("touches" in event && event.touches.length > 0) {
|
|
125
|
+
clientX = event.touches[0].clientX;
|
|
126
|
+
clientY = event.touches[0].clientY;
|
|
127
|
+
}
|
|
128
|
+
else if ("clientX" in event) {
|
|
129
|
+
clientX = event.clientX;
|
|
130
|
+
clientY = event.clientY;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const resolved = this.coords.resolvePointerCoordinates(clientX, clientY);
|
|
136
|
+
if (!resolved) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
let source = InputSource.MOUSE;
|
|
140
|
+
if ("pointerType" in event) {
|
|
141
|
+
source =
|
|
142
|
+
event.pointerType === "touch" ? InputSource.TOUCH : InputSource.MOUSE;
|
|
143
|
+
}
|
|
144
|
+
else if ("touches" in event) {
|
|
145
|
+
source = InputSource.TOUCH;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
id: "pointerId" in event ? event.pointerId : 0,
|
|
149
|
+
action,
|
|
150
|
+
source,
|
|
151
|
+
x: resolved.x,
|
|
152
|
+
y: resolved.y,
|
|
153
|
+
timestamp: performance.now(),
|
|
154
|
+
userId,
|
|
155
|
+
modifiers: {
|
|
156
|
+
shift: event.shiftKey || false,
|
|
157
|
+
ctrl: event.ctrlKey || false,
|
|
158
|
+
alt: event.altKey || false,
|
|
159
|
+
meta: event.metaKey || false,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Create an InputSignal from a KeyboardEvent.
|
|
165
|
+
*/
|
|
166
|
+
createKeySignal(event, userId = "local") {
|
|
167
|
+
return {
|
|
168
|
+
id: 0,
|
|
169
|
+
action: InputAction.KEY,
|
|
170
|
+
source: InputSource.KEYBOARD,
|
|
171
|
+
x: 0,
|
|
172
|
+
y: 0,
|
|
173
|
+
timestamp: performance.now(),
|
|
174
|
+
userId,
|
|
175
|
+
key: event.key,
|
|
176
|
+
modifiers: {
|
|
177
|
+
shift: event.shiftKey,
|
|
178
|
+
ctrl: event.ctrlKey,
|
|
179
|
+
alt: event.altKey,
|
|
180
|
+
meta: event.metaKey,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// ===========================================================================
|
|
185
|
+
// INTERNAL HELPERS
|
|
186
|
+
// ===========================================================================
|
|
187
|
+
/**
|
|
188
|
+
* Determine the scheduling priority for an action.
|
|
189
|
+
*/
|
|
190
|
+
determinePriority(action) {
|
|
191
|
+
switch (action) {
|
|
192
|
+
case InputAction.START:
|
|
193
|
+
case InputAction.END:
|
|
194
|
+
case InputAction.CANCEL:
|
|
195
|
+
case InputAction.KEY:
|
|
196
|
+
// These need immediate processing (for preventDefault, state changes)
|
|
197
|
+
return TaskPriority.CRITICAL;
|
|
198
|
+
case InputAction.MOVE:
|
|
199
|
+
// Move events can be batched for performance
|
|
200
|
+
return TaskPriority.VISUAL;
|
|
201
|
+
default:
|
|
202
|
+
return TaskPriority.VISUAL;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ===========================================================================
|
|
206
|
+
// GETTERS (For Testing/Debugging)
|
|
207
|
+
// ===========================================================================
|
|
208
|
+
/**
|
|
209
|
+
* Get the current container bounds.
|
|
210
|
+
*/
|
|
211
|
+
getContainerRect() {
|
|
212
|
+
return this.coords.getContainerRect();
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the current plot bounds.
|
|
216
|
+
*/
|
|
217
|
+
getPlotBounds() {
|
|
218
|
+
return this.coords.getPlotBounds();
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Check if the engine has been disposed.
|
|
222
|
+
*/
|
|
223
|
+
isDisposed() {
|
|
224
|
+
return this.disposed;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Manages the execution timing of engine tasks.
|
|
5
|
+
* Critical tasks (pointer down) run synchronously.
|
|
6
|
+
* Visual tasks (hover) are batched to requestAnimationFrame.
|
|
7
|
+
*/
|
|
8
|
+
import { EngineEvent, TaskPriority } from "./types";
|
|
9
|
+
export type TaskHandler<T = unknown> = (event: EngineEvent<T>) => void;
|
|
10
|
+
/**
|
|
11
|
+
* The Scheduler controls when events are dispatched to sensors.
|
|
12
|
+
* It uses a priority-based system to ensure critical interactions
|
|
13
|
+
* (like drag start) happen immediately, while visual updates
|
|
14
|
+
* (like hover highlights) are batched for performance.
|
|
15
|
+
*/
|
|
16
|
+
export declare class Scheduler<T = unknown> {
|
|
17
|
+
private visualQueue;
|
|
18
|
+
private idleQueue;
|
|
19
|
+
private rafId;
|
|
20
|
+
private handler;
|
|
21
|
+
/**
|
|
22
|
+
* Register the handler that will process events.
|
|
23
|
+
* In the full system, this is the EventBus.dispatch method.
|
|
24
|
+
*/
|
|
25
|
+
setHandler(handler: TaskHandler<T>): void;
|
|
26
|
+
/**
|
|
27
|
+
* Schedule a task for execution.
|
|
28
|
+
*
|
|
29
|
+
* @param priority - The priority level of the task
|
|
30
|
+
* @param event - The engine event to dispatch
|
|
31
|
+
*/
|
|
32
|
+
schedule(priority: TaskPriority, event: EngineEvent<T>): void;
|
|
33
|
+
/**
|
|
34
|
+
* Execute a critical task immediately.
|
|
35
|
+
* This is synchronous to allow preventDefault() on the original event.
|
|
36
|
+
*/
|
|
37
|
+
private executeCritical;
|
|
38
|
+
/**
|
|
39
|
+
* Schedule a flush of the visual queue on the next animation frame.
|
|
40
|
+
*/
|
|
41
|
+
private scheduleVisualFlush;
|
|
42
|
+
/**
|
|
43
|
+
* Process all queued visual tasks.
|
|
44
|
+
* Only the most recent event per input ID is processed (coalescing).
|
|
45
|
+
*/
|
|
46
|
+
private flushVisualQueue;
|
|
47
|
+
/**
|
|
48
|
+
* Schedule a flush of the idle queue using requestIdleCallback.
|
|
49
|
+
*/
|
|
50
|
+
private scheduleIdleFlush;
|
|
51
|
+
/**
|
|
52
|
+
* Process all queued idle tasks.
|
|
53
|
+
*/
|
|
54
|
+
private flushIdleQueue;
|
|
55
|
+
/**
|
|
56
|
+
* Cancel all pending tasks and clean up.
|
|
57
|
+
*/
|
|
58
|
+
dispose(): void;
|
|
59
|
+
}
|