@cratis/components 0.1.9 → 0.1.12

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.
Files changed (258) hide show
  1. package/dist/cjs/CommandForm/CommandFormFields.js +9 -3
  2. package/dist/cjs/CommandForm/CommandFormFields.js.map +1 -1
  3. package/dist/cjs/CommandForm/ValidationMessage.js +24 -0
  4. package/dist/cjs/CommandForm/ValidationMessage.js.map +1 -0
  5. package/dist/cjs/CommandForm/asCommandFormField.js +47 -0
  6. package/dist/cjs/CommandForm/asCommandFormField.js.map +1 -0
  7. package/dist/cjs/CommandForm/fields/CheckboxField.js +13 -0
  8. package/dist/cjs/CommandForm/fields/CheckboxField.js.map +1 -0
  9. package/dist/cjs/CommandForm/fields/DropdownField.js +13 -0
  10. package/dist/cjs/CommandForm/fields/DropdownField.js.map +1 -0
  11. package/dist/cjs/CommandForm/fields/InputTextField.js +13 -0
  12. package/dist/cjs/CommandForm/fields/InputTextField.js.map +1 -0
  13. package/dist/cjs/CommandForm/fields/NumberField.js +13 -0
  14. package/dist/cjs/CommandForm/fields/NumberField.js.map +1 -0
  15. package/dist/cjs/CommandForm/fields/SliderField.js +17 -0
  16. package/dist/cjs/CommandForm/fields/SliderField.js.map +1 -0
  17. package/dist/cjs/CommandForm/fields/TextAreaField.js +13 -0
  18. package/dist/cjs/CommandForm/fields/TextAreaField.js.map +1 -0
  19. package/dist/cjs/CommandForm/index.js +15 -7
  20. package/dist/cjs/CommandForm/index.js.map +1 -1
  21. package/dist/cjs/PivotViewer/PivotViewer.css +1258 -0
  22. package/dist/cjs/PivotViewer/PivotViewer.js +14 -0
  23. package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
  24. package/dist/cjs/PivotViewer/components/PivotCanvas.js +33 -10
  25. package/dist/cjs/PivotViewer/components/PivotCanvas.js.map +1 -1
  26. package/dist/cjs/PivotViewer/components/PivotViewerMain.js +1 -1
  27. package/dist/cjs/PivotViewer/components/PivotViewerMain.js.map +1 -1
  28. package/dist/cjs/PivotViewer/components/Spinner.css +77 -0
  29. package/dist/cjs/PivotViewer/components/pivot/sprites.js +79 -15
  30. package/dist/cjs/PivotViewer/components/pivot/sprites.js.map +1 -1
  31. package/dist/cjs/PivotViewer/components/pivot/visibility.js +36 -10
  32. package/dist/cjs/PivotViewer/components/pivot/visibility.js.map +1 -1
  33. package/dist/cjs/PivotViewer/engine/layout.js +2 -1
  34. package/dist/cjs/PivotViewer/engine/layout.js.map +1 -1
  35. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js +37 -2
  36. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  37. package/dist/cjs/PivotViewer/index.js +3 -0
  38. package/dist/cjs/PivotViewer/index.js.map +1 -1
  39. package/dist/cjs/PivotViewer/types.js +22 -0
  40. package/dist/cjs/PivotViewer/types.js.map +1 -0
  41. package/dist/cjs/TimeMachine/EventsView.css +213 -0
  42. package/dist/cjs/TimeMachine/TimeMachine.css +567 -0
  43. package/dist/cjs/TimeMachine/TimeMachine.js +8 -3
  44. package/dist/cjs/TimeMachine/TimeMachine.js.map +1 -1
  45. package/dist/esm/CommandForm/CommandForm.stories.d.ts +1 -0
  46. package/dist/esm/CommandForm/CommandForm.stories.d.ts.map +1 -1
  47. package/dist/esm/CommandForm/CommandForm.stories.js +34 -1
  48. package/dist/esm/CommandForm/CommandForm.stories.js.map +1 -1
  49. package/dist/esm/CommandForm/CommandFormFields.d.ts.map +1 -1
  50. package/dist/esm/CommandForm/CommandFormFields.js +9 -3
  51. package/dist/esm/CommandForm/CommandFormFields.js.map +1 -1
  52. package/dist/esm/CommandForm/UserRegistrationCommand.d.ts +63 -0
  53. package/dist/esm/CommandForm/UserRegistrationCommand.d.ts.map +1 -0
  54. package/dist/esm/CommandForm/UserRegistrationCommand.js +143 -0
  55. package/dist/esm/CommandForm/UserRegistrationCommand.js.map +1 -0
  56. package/dist/esm/CommandForm/ValidationMessage.d.ts +8 -0
  57. package/dist/esm/CommandForm/ValidationMessage.d.ts.map +1 -0
  58. package/dist/esm/CommandForm/ValidationMessage.js +22 -0
  59. package/dist/esm/CommandForm/ValidationMessage.js.map +1 -0
  60. package/dist/esm/CommandForm/asCommandFormField.d.ts +32 -0
  61. package/dist/esm/CommandForm/asCommandFormField.d.ts.map +1 -0
  62. package/dist/esm/CommandForm/asCommandFormField.js +45 -0
  63. package/dist/esm/CommandForm/asCommandFormField.js.map +1 -0
  64. package/dist/esm/CommandForm/fields/CheckboxField.d.ts +10 -0
  65. package/dist/esm/CommandForm/fields/CheckboxField.d.ts.map +1 -0
  66. package/dist/esm/CommandForm/fields/CheckboxField.js +11 -0
  67. package/dist/esm/CommandForm/fields/CheckboxField.js.map +1 -0
  68. package/dist/esm/CommandForm/fields/DropdownField.d.ts +15 -0
  69. package/dist/esm/CommandForm/fields/DropdownField.d.ts.map +1 -0
  70. package/dist/esm/CommandForm/fields/DropdownField.js +11 -0
  71. package/dist/esm/CommandForm/fields/DropdownField.js.map +1 -0
  72. package/dist/esm/CommandForm/fields/InputTextField.d.ts +11 -0
  73. package/dist/esm/CommandForm/fields/InputTextField.d.ts.map +1 -0
  74. package/dist/esm/CommandForm/fields/InputTextField.js +11 -0
  75. package/dist/esm/CommandForm/fields/InputTextField.js.map +1 -0
  76. package/dist/esm/CommandForm/fields/NumberField.d.ts +13 -0
  77. package/dist/esm/CommandForm/fields/NumberField.d.ts.map +1 -0
  78. package/dist/esm/CommandForm/fields/NumberField.js +11 -0
  79. package/dist/esm/CommandForm/fields/NumberField.js.map +1 -0
  80. package/dist/esm/CommandForm/fields/SliderField.d.ts +12 -0
  81. package/dist/esm/CommandForm/fields/SliderField.d.ts.map +1 -0
  82. package/dist/esm/CommandForm/fields/SliderField.js +15 -0
  83. package/dist/esm/CommandForm/fields/SliderField.js.map +1 -0
  84. package/dist/esm/CommandForm/fields/TextAreaField.d.ts +12 -0
  85. package/dist/esm/CommandForm/fields/TextAreaField.d.ts.map +1 -0
  86. package/dist/esm/CommandForm/fields/TextAreaField.js +11 -0
  87. package/dist/esm/CommandForm/fields/TextAreaField.js.map +1 -0
  88. package/dist/esm/CommandForm/fields/index.d.ts +7 -0
  89. package/dist/esm/CommandForm/fields/index.d.ts.map +1 -0
  90. package/dist/esm/CommandForm/fields/index.js +7 -0
  91. package/dist/esm/CommandForm/fields/index.js.map +1 -0
  92. package/dist/esm/CommandForm/index.d.ts +3 -4
  93. package/dist/esm/CommandForm/index.d.ts.map +1 -1
  94. package/dist/esm/CommandForm/index.js +8 -4
  95. package/dist/esm/CommandForm/index.js.map +1 -1
  96. package/dist/esm/PivotViewer/PivotViewer.css +1258 -0
  97. package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
  98. package/dist/esm/PivotViewer/PivotViewer.js +14 -0
  99. package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
  100. package/dist/esm/PivotViewer/PivotViewer.stories.d.ts +1 -0
  101. package/dist/esm/PivotViewer/PivotViewer.stories.d.ts.map +1 -1
  102. package/dist/esm/PivotViewer/PivotViewer.stories.js +43 -3
  103. package/dist/esm/PivotViewer/PivotViewer.stories.js.map +1 -1
  104. package/dist/esm/PivotViewer/components/PivotCanvas.d.ts.map +1 -1
  105. package/dist/esm/PivotViewer/components/PivotCanvas.js +33 -10
  106. package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
  107. package/dist/esm/PivotViewer/components/PivotViewerMain.js +1 -1
  108. package/dist/esm/PivotViewer/components/PivotViewerMain.js.map +1 -1
  109. package/dist/esm/PivotViewer/components/Spinner.css +77 -0
  110. package/dist/esm/PivotViewer/components/pivot/sprites.d.ts.map +1 -1
  111. package/dist/esm/PivotViewer/components/pivot/sprites.js +79 -15
  112. package/dist/esm/PivotViewer/components/pivot/sprites.js.map +1 -1
  113. package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
  114. package/dist/esm/PivotViewer/components/pivot/visibility.js +36 -10
  115. package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
  116. package/dist/esm/PivotViewer/engine/layout.js +2 -1
  117. package/dist/esm/PivotViewer/engine/layout.js.map +1 -1
  118. package/dist/esm/PivotViewer/engine/pivot.worker.d.ts.map +1 -1
  119. package/dist/esm/PivotViewer/engine/pivot.worker.js +22 -7
  120. package/dist/esm/PivotViewer/engine/pivot.worker.js.map +1 -1
  121. package/dist/esm/PivotViewer/hooks/useFilteredData.d.ts +2 -2
  122. package/dist/esm/PivotViewer/hooks/useFilteredData.d.ts.map +1 -1
  123. package/dist/esm/PivotViewer/hooks/useFilteredData.js +4 -2
  124. package/dist/esm/PivotViewer/hooks/useFilteredData.js.map +1 -1
  125. package/dist/esm/PivotViewer/hooks/usePivotEngine.d.ts.map +1 -1
  126. package/dist/esm/PivotViewer/hooks/usePivotEngine.js +37 -2
  127. package/dist/esm/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  128. package/dist/esm/PivotViewer/index.d.ts +2 -1
  129. package/dist/esm/PivotViewer/index.d.ts.map +1 -1
  130. package/dist/esm/PivotViewer/index.js +1 -0
  131. package/dist/esm/PivotViewer/index.js.map +1 -1
  132. package/dist/esm/PivotViewer/types.d.ts +4 -1
  133. package/dist/esm/PivotViewer/types.d.ts.map +1 -1
  134. package/dist/esm/PivotViewer/types.js +19 -2
  135. package/dist/esm/PivotViewer/types.js.map +1 -1
  136. package/dist/esm/TimeMachine/EventsView.css +213 -0
  137. package/dist/esm/TimeMachine/TimeMachine.css +567 -0
  138. package/dist/esm/TimeMachine/TimeMachine.d.ts.map +1 -1
  139. package/dist/esm/TimeMachine/TimeMachine.js +8 -3
  140. package/dist/esm/TimeMachine/TimeMachine.js.map +1 -1
  141. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  142. package/package.json +31 -32
  143. package/.storybook/main.ts +0 -24
  144. package/CommandDialog/CommandDialog.stories.tsx +0 -25
  145. package/CommandDialog/CommandDialog.tsx +0 -161
  146. package/CommandDialog/index.ts +0 -4
  147. package/CommandForm/CommandForm.stories.tsx +0 -24
  148. package/CommandForm/CommandForm.tsx +0 -266
  149. package/CommandForm/CommandFormField.tsx +0 -27
  150. package/CommandForm/CommandFormFields.tsx +0 -142
  151. package/CommandForm/DatePickerField.tsx +0 -57
  152. package/CommandForm/DropdownField.tsx +0 -65
  153. package/CommandForm/InputTextField.tsx +0 -62
  154. package/CommandForm/SliderField.tsx +0 -68
  155. package/CommandForm/index.ts +0 -10
  156. package/Common/ErrorBoundary.stories.tsx +0 -10
  157. package/Common/ErrorBoundary.tsx +0 -41
  158. package/Common/FormElement.stories.tsx +0 -10
  159. package/Common/FormElement.tsx +0 -20
  160. package/Common/Page.stories.tsx +0 -10
  161. package/Common/Page.tsx +0 -21
  162. package/Common/index.ts +0 -6
  163. package/DataPage/DataPage.stories.tsx +0 -10
  164. package/DataPage/DataPage.tsx +0 -191
  165. package/DataPage/index.ts +0 -4
  166. package/DataTables/DataTableForObservableQuery.stories.tsx +0 -10
  167. package/DataTables/DataTableForObservableQuery.tsx +0 -97
  168. package/DataTables/DataTableForQuery.stories.tsx +0 -10
  169. package/DataTables/DataTableForQuery.tsx +0 -97
  170. package/DataTables/index.ts +0 -5
  171. package/Dialogs/BusyIndicatorDialog.stories.tsx +0 -26
  172. package/Dialogs/BusyIndicatorDialog.tsx +0 -26
  173. package/Dialogs/ConfirmationDialog.stories.tsx +0 -36
  174. package/Dialogs/ConfirmationDialog.tsx +0 -75
  175. package/Dialogs/index.ts +0 -5
  176. package/Dropdown/Dropdown.tsx +0 -23
  177. package/Dropdown/index.ts +0 -4
  178. package/PivotViewer/PivotViewer.stories.tsx +0 -24
  179. package/PivotViewer/PivotViewer.tsx +0 -791
  180. package/PivotViewer/components/AxisLabels.tsx +0 -69
  181. package/PivotViewer/components/DetailPanel.tsx +0 -108
  182. package/PivotViewer/components/FilterPanel.tsx +0 -189
  183. package/PivotViewer/components/FilterPanelContainer.tsx +0 -10
  184. package/PivotViewer/components/PivotCanvas.tsx +0 -660
  185. package/PivotViewer/components/PivotViewerMain.tsx +0 -229
  186. package/PivotViewer/components/RangeHistogramFilter.tsx +0 -220
  187. package/PivotViewer/components/Spinner.tsx +0 -21
  188. package/PivotViewer/components/Toolbar.tsx +0 -130
  189. package/PivotViewer/components/ToolbarContainer.tsx +0 -10
  190. package/PivotViewer/components/index.ts +0 -12
  191. package/PivotViewer/components/pivot/animation.ts +0 -108
  192. package/PivotViewer/components/pivot/buckets.ts +0 -152
  193. package/PivotViewer/components/pivot/colorResolver.ts +0 -67
  194. package/PivotViewer/components/pivot/constants.ts +0 -46
  195. package/PivotViewer/components/pivot/sprites.ts +0 -265
  196. package/PivotViewer/components/pivot/visibility.ts +0 -319
  197. package/PivotViewer/constants.ts +0 -9
  198. package/PivotViewer/engine/layout.ts +0 -149
  199. package/PivotViewer/engine/pivot.worker.ts +0 -86
  200. package/PivotViewer/engine/store.ts +0 -437
  201. package/PivotViewer/engine/types.ts +0 -255
  202. package/PivotViewer/hooks/index.ts +0 -13
  203. package/PivotViewer/hooks/useContainerDimensions.ts +0 -45
  204. package/PivotViewer/hooks/useDimensionState.ts +0 -53
  205. package/PivotViewer/hooks/useFilterOptions.ts +0 -36
  206. package/PivotViewer/hooks/useFilterPanelDrag.ts +0 -49
  207. package/PivotViewer/hooks/useFilterState.ts +0 -106
  208. package/PivotViewer/hooks/useFilteredData.ts +0 -119
  209. package/PivotViewer/hooks/usePanning.ts +0 -163
  210. package/PivotViewer/hooks/usePivotEngine.ts +0 -252
  211. package/PivotViewer/hooks/useSelectedItem.ts +0 -402
  212. package/PivotViewer/hooks/useWheelZoom.ts +0 -114
  213. package/PivotViewer/hooks/useZoomState.ts +0 -34
  214. package/PivotViewer/index.ts +0 -7
  215. package/PivotViewer/types.ts +0 -59
  216. package/PivotViewer/utils/animations.ts +0 -249
  217. package/PivotViewer/utils/constants.ts +0 -20
  218. package/PivotViewer/utils/index.ts +0 -6
  219. package/PivotViewer/utils/selection.ts +0 -292
  220. package/PivotViewer/utils/utils.ts +0 -259
  221. package/TimeMachine/EventsView.stories.tsx +0 -10
  222. package/TimeMachine/EventsView.tsx +0 -119
  223. package/TimeMachine/Properties.stories.tsx +0 -10
  224. package/TimeMachine/Properties.tsx +0 -98
  225. package/TimeMachine/ReadModelView.stories.tsx +0 -10
  226. package/TimeMachine/ReadModelView.tsx +0 -143
  227. package/TimeMachine/TimeMachine.stories.tsx +0 -10
  228. package/TimeMachine/TimeMachine.tsx +0 -244
  229. package/TimeMachine/index.ts +0 -8
  230. package/TimeMachine/types.ts +0 -23
  231. package/dist/cjs/CommandForm/DatePickerField.js +0 -31
  232. package/dist/cjs/CommandForm/DatePickerField.js.map +0 -1
  233. package/dist/cjs/CommandForm/DropdownField.js +0 -31
  234. package/dist/cjs/CommandForm/DropdownField.js.map +0 -1
  235. package/dist/cjs/CommandForm/InputTextField.js +0 -32
  236. package/dist/cjs/CommandForm/InputTextField.js.map +0 -1
  237. package/dist/cjs/CommandForm/SliderField.js +0 -34
  238. package/dist/cjs/CommandForm/SliderField.js.map +0 -1
  239. package/dist/esm/CommandForm/DatePickerField.d.ts +0 -20
  240. package/dist/esm/CommandForm/DatePickerField.d.ts.map +0 -1
  241. package/dist/esm/CommandForm/DatePickerField.js +0 -29
  242. package/dist/esm/CommandForm/DatePickerField.js.map +0 -1
  243. package/dist/esm/CommandForm/DropdownField.d.ts +0 -24
  244. package/dist/esm/CommandForm/DropdownField.d.ts.map +0 -1
  245. package/dist/esm/CommandForm/DropdownField.js +0 -29
  246. package/dist/esm/CommandForm/DropdownField.js.map +0 -1
  247. package/dist/esm/CommandForm/InputTextField.d.ts +0 -20
  248. package/dist/esm/CommandForm/InputTextField.d.ts.map +0 -1
  249. package/dist/esm/CommandForm/InputTextField.js +0 -30
  250. package/dist/esm/CommandForm/InputTextField.js.map +0 -1
  251. package/dist/esm/CommandForm/SliderField.d.ts +0 -23
  252. package/dist/esm/CommandForm/SliderField.d.ts.map +0 -1
  253. package/dist/esm/CommandForm/SliderField.js +0 -32
  254. package/dist/esm/CommandForm/SliderField.js.map +0 -1
  255. package/global.d.ts +0 -11
  256. package/index.ts +0 -22
  257. package/useOverlayZIndex.ts +0 -32
  258. package/vite.config.ts +0 -80
@@ -1,292 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import { animateZoomAndScroll, calculateCenterScrollPosition, smoothScrollTo } from './animations';
5
- import { ZOOM_MAX, MIN_ZOOM_ON_SELECT, ZOOM_MULTIPLIER, DETAIL_PANEL_WIDTH } from './constants';
6
- import type { ViewMode } from '../components/Toolbar';
7
-
8
- export interface SelectionState {
9
- zoom: number;
10
- scrollLeft: number;
11
- scrollTop: number;
12
- }
13
-
14
- export interface CardClickHandlerParams<TItem> {
15
- item: TItem;
16
- itemId: string | number;
17
- selectedItemId: string | number | null;
18
- container: HTMLElement;
19
- cardPosition: { x: number; y: number; width: number; height: number } | null;
20
- targetCardPosition?: { x: number; y: number; width: number; height: number } | null;
21
- getCardPositionAtZoom?: (zoom: number) => { x: number; y: number; width: number; height: number } | null;
22
- getLayoutSizeAtZoom?: (zoom: number) => { width: number; height: number };
23
- spacer?: HTMLElement | null;
24
- viewMode: ViewMode;
25
- zoomLevel: number;
26
- totalHeight?: number;
27
- preSelectionState: SelectionState | null;
28
- startScrollPosition?: { x: number; y: number };
29
- setZoomLevel: (zoom: number) => void;
30
- setIsZooming: (isZooming: boolean) => void;
31
- setSelectedItem: (item: TItem | null) => void;
32
- setPreSelectionState: (state: SelectionState | null) => void;
33
- }
34
-
35
- /**
36
- * Handle card click for selection with zoom and scroll animation
37
- */
38
- export function handleCardSelection<TItem>({
39
- itemId,
40
- selectedItemId,
41
- container,
42
- cardPosition,
43
- targetCardPosition,
44
- getCardPositionAtZoom,
45
- getLayoutSizeAtZoom,
46
- spacer,
47
- viewMode,
48
- zoomLevel,
49
- totalHeight,
50
- preSelectionState,
51
- startScrollPosition,
52
- setZoomLevel,
53
- setIsZooming,
54
- setSelectedItem,
55
- setPreSelectionState,
56
- item,
57
- }: CardClickHandlerParams<TItem>): void {
58
- // Clicking the same card - deselect
59
- if (selectedItemId === itemId) {
60
- deselectCard({
61
- container,
62
- cardPosition,
63
- targetCardPosition,
64
- getCardPositionAtZoom,
65
- getLayoutSizeAtZoom,
66
- spacer,
67
- viewMode,
68
- zoomLevel,
69
- preSelectionState,
70
- setZoomLevel,
71
- setIsZooming,
72
- setSelectedItem,
73
- setPreSelectionState,
74
- });
75
- return;
76
- }
77
-
78
- // First selection - save state and zoom in
79
- const isFirstSelection = selectedItemId === null;
80
-
81
- if (isFirstSelection) {
82
- setPreSelectionState({
83
- zoom: zoomLevel,
84
- scrollLeft: container.scrollLeft,
85
- scrollTop: container.scrollTop,
86
- });
87
- }
88
-
89
- setSelectedItem(item);
90
-
91
- if (isFirstSelection) {
92
- if (viewMode === 'collection') {
93
- // Collection mode: just smooth scroll to center, no zoom
94
- if (cardPosition) {
95
- // In collection mode, we don't have a detail panel width offset because the panel is an overlay or separate
96
- // But if we want to center it, we should consider if the detail panel pushes content
97
- // For now, assume 0 offset as per original code
98
- const { scrollLeft, scrollTop } = calculateCenterScrollPosition(container, cardPosition, zoomLevel, 0, totalHeight);
99
- smoothScrollTo(container, scrollLeft, scrollTop, true);
100
- }
101
- } else {
102
- // Grouped mode: animate zoom and scroll
103
- zoomAndCenterCard({
104
- container,
105
- cardPosition,
106
- targetCardPosition,
107
- getCardPositionAtZoom,
108
- getLayoutSizeAtZoom,
109
- spacer,
110
- itemId,
111
- zoomLevel,
112
- totalHeight,
113
- startScrollPosition,
114
- setZoomLevel,
115
- setIsZooming,
116
- });
117
- }
118
- } else {
119
- // Subsequent selections: just center the new card
120
- if (cardPosition) {
121
- // In collection mode, we don't zoom, so we just center.
122
- // In grouped mode, we might be zoomed in, so we center with offset.
123
- const detailWidth = viewMode === 'collection' ? 0 : DETAIL_PANEL_WIDTH;
124
- const { scrollLeft, scrollTop } = calculateCenterScrollPosition(container, cardPosition, zoomLevel, detailWidth, totalHeight);
125
- smoothScrollTo(container, scrollLeft, scrollTop, true);
126
- }
127
- }
128
- }
129
-
130
- interface DeselectParams {
131
- container: HTMLElement;
132
- cardPosition: { x: number; y: number; width: number; height: number } | null;
133
- targetCardPosition?: { x: number; y: number; width: number; height: number } | null;
134
- getCardPositionAtZoom?: (zoom: number) => { x: number; y: number; width: number; height: number } | null;
135
- getLayoutSizeAtZoom?: (zoom: number) => { width: number; height: number };
136
- spacer?: HTMLElement | null;
137
- viewMode: ViewMode;
138
- zoomLevel: number;
139
- preSelectionState: SelectionState | null;
140
- setZoomLevel: (zoom: number) => void;
141
- setIsZooming: (isZooming: boolean) => void;
142
- setSelectedItem: (item: null) => void;
143
- setPreSelectionState: (state: SelectionState | null) => void;
144
- }
145
-
146
- /**
147
- * Deselect card with zoom-out animation if needed
148
- */
149
- function deselectCard({
150
- container,
151
- cardPosition,
152
- targetCardPosition,
153
- getCardPositionAtZoom,
154
- getLayoutSizeAtZoom,
155
- spacer,
156
- viewMode,
157
- zoomLevel,
158
- preSelectionState,
159
- setZoomLevel,
160
- setIsZooming,
161
- setSelectedItem,
162
- setPreSelectionState,
163
- }: DeselectParams): void {
164
- if (!preSelectionState) {
165
- setSelectedItem(null);
166
- return;
167
- }
168
-
169
- // Collection mode: just scroll back
170
- if (viewMode === 'collection') {
171
- setSelectedItem(null);
172
- smoothScrollTo(container, preSelectionState.scrollLeft, preSelectionState.scrollTop, true);
173
- setPreSelectionState(null);
174
- return;
175
- }
176
-
177
- // Grouped mode: check if zoom changed
178
- const zoomChanged = Math.abs(preSelectionState.zoom - zoomLevel) > 0.001;
179
-
180
- if (!zoomChanged || !cardPosition) {
181
- setSelectedItem(null);
182
- smoothScrollTo(container, preSelectionState.scrollLeft, preSelectionState.scrollTop, true);
183
- setPreSelectionState(null);
184
- return;
185
- }
186
-
187
- // Animate zoom out
188
- setIsZooming(true);
189
-
190
- animateZoomAndScroll({
191
- container,
192
- cardPosition,
193
- targetCardPosition,
194
- getCardPositionAtZoom,
195
- getLayoutSizeAtZoom,
196
- spacer,
197
- startZoom: zoomLevel,
198
- targetZoom: preSelectionState.zoom,
199
- targetScrollLeft: preSelectionState.scrollLeft,
200
- targetScrollTop: preSelectionState.scrollTop,
201
- onUpdate: setZoomLevel,
202
- onComplete: () => {
203
- setIsZooming(false);
204
- setSelectedItem(null);
205
- setPreSelectionState(null);
206
- },
207
- });
208
- }
209
-
210
- interface ZoomAndCenterParams {
211
- container: HTMLElement;
212
- cardPosition: { x: number; y: number; width: number; height: number } | null;
213
- targetCardPosition?: { x: number; y: number; width: number; height: number } | null;
214
- getCardPositionAtZoom?: (zoom: number) => { x: number; y: number; width: number; height: number } | null;
215
- getLayoutSizeAtZoom?: (zoom: number) => { width: number; height: number };
216
- spacer?: HTMLElement | null;
217
- itemId: string | number;
218
- zoomLevel: number;
219
- totalHeight?: number;
220
- startScrollPosition?: { x: number; y: number };
221
- setZoomLevel: (zoom: number) => void;
222
- setIsZooming: (isZooming: boolean) => void;
223
- }
224
-
225
- /**
226
- * Zoom in and center a card
227
- */
228
- function zoomAndCenterCard({
229
- container,
230
- cardPosition,
231
- targetCardPosition,
232
- getCardPositionAtZoom,
233
- getLayoutSizeAtZoom,
234
- spacer,
235
- zoomLevel,
236
- totalHeight,
237
- startScrollPosition,
238
- setZoomLevel,
239
- setIsZooming,
240
- }: ZoomAndCenterParams): void {
241
- const targetZoom = Math.min(ZOOM_MAX, Math.max(MIN_ZOOM_ON_SELECT, zoomLevel * ZOOM_MULTIPLIER));
242
- const shouldZoom = Math.abs(targetZoom - zoomLevel) > 0.001;
243
-
244
- if (!shouldZoom || !cardPosition) {
245
- if (cardPosition) {
246
- const { scrollLeft, scrollTop } = calculateCenterScrollPosition(container, cardPosition, zoomLevel, DETAIL_PANEL_WIDTH, totalHeight);
247
- smoothScrollTo(container, scrollLeft, scrollTop, true);
248
- }
249
- return;
250
- }
251
-
252
- setIsZooming(true);
253
-
254
- // Use targetCardPosition if available, otherwise fallback to cardPosition
255
- const { scrollLeft: targetScrollLeft, scrollTop: targetScrollTop } = calculateCenterScrollPosition(
256
- container,
257
- targetCardPosition || cardPosition,
258
- targetZoom,
259
- DETAIL_PANEL_WIDTH,
260
- totalHeight
261
- );
262
-
263
- animateZoomAndScroll({
264
- container,
265
- cardPosition,
266
- targetCardPosition,
267
- getCardPositionAtZoom,
268
- getLayoutSizeAtZoom,
269
- spacer,
270
- startZoom: zoomLevel,
271
- targetZoom,
272
- targetScrollLeft,
273
- targetScrollTop,
274
- startScrollLeft: startScrollPosition?.x,
275
- startScrollTop: startScrollPosition?.y,
276
- onUpdate: setZoomLevel,
277
- onComplete: () => {
278
- setIsZooming(false);
279
- },
280
- });
281
- }
282
-
283
- /**
284
- * Get card element by ID from container
285
- */
286
- export function getCardElementById(_container: HTMLElement, _itemId: string | number): HTMLElement | null {
287
- // Deprecated: Pixi renderer doesn't use DOM elements for cards
288
- // Keep parameter names prefixed to indicate intentional non-use.
289
- void _container;
290
- void _itemId;
291
- return null;
292
- }
@@ -1,259 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import type {
5
- PivotDimension,
6
- PivotFilter,
7
- PivotFilterOption,
8
- PivotGroup,
9
- PivotPrimitive,
10
- } from '../types';
11
-
12
- export type FilterState = Record<string, Set<string>>;
13
- export type RangeFilterState = Record<string, [number, number] | null>;
14
-
15
- // Zoom configuration
16
- export const ZOOM_MIN = 0.1;
17
- export const ZOOM_MAX = 3;
18
- export const ZOOM_STEP = 0.05;
19
- export const CARDS_PER_COLUMN = 5;
20
- export const BASE_CARD_WIDTH = 180;
21
- export const BASE_CARD_HEIGHT = 140;
22
-
23
- export const toKey = (value: PivotPrimitive): string => {
24
- if (value === undefined) return 'undefined';
25
- if (value === null) return 'null';
26
- if (value instanceof Date) return value.toISOString();
27
- if (typeof value === 'number' && Number.isNaN(value)) return 'nan';
28
- return String(value);
29
- };
30
-
31
- export const defaultFormat = (value: PivotPrimitive): string => {
32
- if (value === undefined) return 'Unknown';
33
- if (value === null) return 'None';
34
- if (value instanceof Date) return value.toLocaleString();
35
- if (typeof value === 'boolean') return value ? 'Yes' : 'No';
36
- return String(value);
37
- };
38
-
39
- export const buildFilterState = <TItem extends object>(
40
- filters: PivotFilter<TItem>[] | undefined,
41
- ): FilterState => {
42
- const state: FilterState = {};
43
- filters?.forEach((filter) => {
44
- state[filter.key] = new Set<string>();
45
- });
46
- return state;
47
- };
48
-
49
- export const buildRangeFilterState = <TItem extends object>(
50
- filters: PivotFilter<TItem>[] | undefined,
51
- ): RangeFilterState => {
52
- const state: RangeFilterState = {};
53
- filters?.forEach((filter) => {
54
- if (filter.type === 'number') {
55
- state[filter.key] = null;
56
- }
57
- });
58
- return state;
59
- };
60
-
61
- export const applyFilters = <TItem extends object>(
62
- data: TItem[],
63
- filters: PivotFilter<TItem>[] | undefined,
64
- state: FilterState,
65
- rangeState: RangeFilterState,
66
- skipKey?: string,
67
- ): TItem[] => {
68
- if (!filters?.length) {
69
- return data;
70
- }
71
-
72
- // Pre-compute active filters to avoid checking empty Sets repeatedly
73
- const activeFilters: Array<{
74
- filter: PivotFilter<TItem>;
75
- selections?: Set<string>;
76
- range?: [number, number];
77
- }> = [];
78
-
79
- for (const filter of filters) {
80
- if (filter.key === skipKey) {
81
- continue;
82
- }
83
-
84
- if (filter.type === 'number') {
85
- const range = rangeState[filter.key];
86
- if (range) {
87
- activeFilters.push({ filter, range });
88
- }
89
- } else {
90
- const selections = state[filter.key];
91
- if (selections && selections.size > 0) {
92
- activeFilters.push({ filter, selections });
93
- }
94
- }
95
- }
96
-
97
- // Early exit if no active filters
98
- if (activeFilters.length === 0) {
99
- return data;
100
- }
101
-
102
- return data.filter((item) => {
103
- for (const { filter, selections, range } of activeFilters) {
104
- if (range) {
105
- const value = filter.getValue(item);
106
- const numValue = typeof value === 'number' ? value : Number(value);
107
- if (!Number.isNaN(numValue) && (numValue < range[0] || numValue > range[1])) {
108
- return false;
109
- }
110
- } else if (selections) {
111
- const valueKey = toKey(filter.getValue(item));
112
- if (!selections.has(valueKey)) {
113
- return false;
114
- }
115
- }
116
- }
117
- return true;
118
- });
119
- };
120
-
121
- export const computeFilterOptions = <TItem extends object>(
122
- data: TItem[],
123
- filter: PivotFilter<TItem>,
124
- ): PivotFilterOption[] => {
125
- if (filter.options?.length) {
126
- return filter.options;
127
- }
128
-
129
- const counts = new Map<string, { option: PivotFilterOption; count: number }>();
130
-
131
- data.forEach((item) => {
132
- const value = filter.getValue(item);
133
- const key = toKey(value);
134
- const existing = counts.get(key);
135
- if (existing) {
136
- existing.count += 1;
137
- } else {
138
- counts.set(key, {
139
- option: {
140
- key,
141
- label: defaultFormat(value),
142
- value,
143
- count: 1,
144
- },
145
- count: 1,
146
- });
147
- }
148
- });
149
-
150
- const options = Array.from(counts.values()).map(({ option, count }) => ({
151
- ...option,
152
- count,
153
- }));
154
-
155
- return filter.sort ? options.sort(filter.sort) : options.sort((a, b) => b.count - a.count);
156
- };
157
-
158
- export const renderOptionCount = (count: number | undefined): string | number =>
159
- typeof count === 'number' ? count : '';
160
-
161
- export const computeNumericRange = <TItem extends object>(
162
- data: TItem[],
163
- filter: PivotFilter<TItem>,
164
- ): { min: number; max: number; values: PivotPrimitive[] } => {
165
- const values: PivotPrimitive[] = [];
166
- let min = Infinity;
167
- let max = -Infinity;
168
-
169
- data.forEach((item) => {
170
- const value = filter.getValue(item);
171
- values.push(value);
172
- const numValue = typeof value === 'number' ? value : Number(value);
173
- if (!Number.isNaN(numValue)) {
174
- min = Math.min(min, numValue);
175
- max = Math.max(max, numValue);
176
- }
177
- });
178
-
179
- return {
180
- min: min === Infinity ? 0 : min,
181
- max: max === -Infinity ? 100 : max,
182
- values,
183
- };
184
- };
185
-
186
- export const groupData = <TItem extends object>(
187
- data: TItem[],
188
- dimension: PivotDimension<TItem>,
189
- ): PivotGroup<TItem>[] => {
190
- const groups = new Map<string, PivotGroup<TItem>>();
191
-
192
- // Cache the formatValue function if it exists
193
- const formatValue = dimension.formatValue;
194
-
195
- data.forEach((item) => {
196
- const rawValue = dimension.getValue(item);
197
- const key = toKey(rawValue) || 'default';
198
- const group = groups.get(key);
199
-
200
- if (group) {
201
- group.items.push(item);
202
- } else {
203
- const label = formatValue ? formatValue(rawValue) : defaultFormat(rawValue);
204
- groups.set(key, {
205
- key,
206
- label,
207
- value: rawValue,
208
- items: [item],
209
- });
210
- }
211
- });
212
-
213
- const result = Array.from(groups.values());
214
- return dimension.sort ? result.sort(dimension.sort) : result.sort((a, b) => a.label.localeCompare(b.label));
215
- };
216
-
217
- /**
218
- * Reorder items for a CSS Grid that displays bottom-up, left-to-right.
219
- * CSS Grid fills top-to-bottom, left-to-right by default.
220
- *
221
- * Visual goal (items fill bottom row first, then row above, etc.):
222
- * Grid Row 0 (top): [4] [5] [6] [ ] [ ] <- partial top row, empties on RIGHT
223
- * Grid Row 1 (bottom): [0] [1] [2] [3] [4] <- full bottom row
224
- *
225
- * Returns array with nulls for empty cells that need placeholder rendering.
226
- */
227
- export const reorderForBottomUpGrid = <TItem,>(items: TItem[], columns: number): (TItem | null)[] => {
228
- if (items.length === 0) return [];
229
-
230
- const totalRows = Math.ceil(items.length / columns);
231
- const itemsInTopRow = items.length % columns || columns;
232
-
233
- const result: (TItem | null)[] = [];
234
-
235
- // Top row: items from the "overflow" portion, plus empty cells on the right
236
- const topRowStartIndex = items.length - itemsInTopRow;
237
- for (let col = 0; col < columns; col++) {
238
- if (col < itemsInTopRow) {
239
- result.push(items[topRowStartIndex + col]);
240
- } else {
241
- result.push(null); // Empty cell on right side of top row
242
- }
243
- }
244
-
245
- // Remaining rows (from second-to-top down to bottom)
246
- // These are full rows, containing items 0 to (items.length - itemsInTopRow - 1)
247
- for (let row = 1; row < totalRows; row++) {
248
- // This grid row corresponds to visual row (totalRows - 1 - row) from bottom
249
- // Visual row 0 = bottom, visual row (totalRows-1) = top
250
- const visualRowFromBottom = totalRows - 1 - row;
251
- const rowStartIndex = visualRowFromBottom * columns;
252
-
253
- for (let col = 0; col < columns; col++) {
254
- result.push(items[rowStartIndex + col]);
255
- }
256
- }
257
-
258
- return result;
259
- };
@@ -1,10 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import React from 'react';
5
- import * as Comp from './EventsView';
6
- const Component: React.ComponentType<any> | undefined = (Comp as any).default || (Object.values(Comp)[0] as any);
7
-
8
- export default { title: 'TimeMachine/EventsView', component: Component };
9
-
10
- export const Default = () => (Component ? <Component /> : <div>Unable to render component</div>);
@@ -1,119 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import React, { useEffect, useRef, useState } from 'react';
5
- import { Timeline } from 'primereact/timeline';
6
- import type { Event } from './types';
7
- import { Properties } from './Properties';
8
- import './EventsView.css';
9
-
10
- interface EventsViewProps {
11
- events: Event[];
12
- }
13
-
14
- export const EventsView: React.FC<EventsViewProps> = ({ events }) => {
15
- // Use test data if no events provided
16
- const displayEvents = events.length > 0 ? events : [];
17
- const containerRef = useRef<HTMLDivElement>(null);
18
- const [canScrollUp, setCanScrollUp] = useState(false);
19
- const [canScrollDown, setCanScrollDown] = useState(false);
20
-
21
- const updateScrollState = () => {
22
- const container = containerRef.current;
23
- if (!container) {
24
- setCanScrollUp(false);
25
- setCanScrollDown(false);
26
- return;
27
- }
28
-
29
- const { scrollTop, scrollHeight, clientHeight } = container;
30
- const epsilon = 1;
31
- setCanScrollUp(scrollTop > epsilon);
32
- setCanScrollDown(scrollTop + clientHeight < scrollHeight - epsilon);
33
- };
34
-
35
- useEffect(() => {
36
- updateScrollState();
37
- const container = containerRef.current;
38
- if (!container) return;
39
-
40
- const handleScroll = () => updateScrollState();
41
- container.addEventListener('scroll', handleScroll);
42
- return () => container.removeEventListener('scroll', handleScroll);
43
- }, [displayEvents.length]);
44
-
45
- const renderEventCard = (event: Event, position: 'left' | 'right') => {
46
- const isLeft = position === 'left';
47
-
48
- return (
49
- <div className={`events-view-event-card events-view-event-card--${position}`}>
50
- <div className={`events-view-event-header ${isLeft ? 'events-view-event-header--right' : ''}`}>
51
- <h3 className={`events-view-event-name ${isLeft ? 'events-view-event-name--right' : ''}`}>{event.type}</h3>
52
- <div className={`events-view-event-timestamp ${isLeft ? 'events-view-event-timestamp--right' : ''}`}>
53
- {event.occurred.toLocaleString()}
54
- </div>
55
- </div>
56
- <div className="events-view-event-properties">
57
- <Properties data={event.content || {}} align="left" />
58
- </div>
59
- </div>
60
- );
61
- };
62
-
63
- const customContent = (event: Event, index: number) => {
64
- // PrimeReact places even indices (0,2,4,...) on the right, odd on the left
65
- const position = index % 2 === 0 ? 'right' : 'left';
66
- return renderEventCard(event, position);
67
- };
68
-
69
- const customMarker = () => {
70
- return (
71
- <div className="events-view-marker">
72
- <div className="events-view-marker-dot"></div>
73
- </div>
74
- );
75
- };
76
-
77
- const scrollToTop = () => containerRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
78
- const scrollToBottom = () => {
79
- const container = containerRef.current;
80
- if (!container) return;
81
- container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
82
- };
83
-
84
- return (
85
- <div className="events-view-container" ref={containerRef}>
86
- {canScrollUp && (
87
- <div className="events-view-scroll-button-wrapper events-view-scroll-button-wrapper--top">
88
- <button
89
- type="button"
90
- className="events-view-scroll-button events-view-scroll-button--top"
91
- onClick={scrollToTop}
92
- aria-label="Scroll to top"
93
- >
94
- <i className="pi pi-arrow-up" />
95
- </button>
96
- </div>
97
- )}
98
- <Timeline
99
- value={displayEvents}
100
- align="alternate"
101
- content={customContent}
102
- marker={customMarker}
103
- className="events-view-timeline"
104
- />
105
- {canScrollDown && (
106
- <div className="events-view-scroll-button-wrapper events-view-scroll-button-wrapper--bottom">
107
- <button
108
- type="button"
109
- className="events-view-scroll-button events-view-scroll-button--bottom"
110
- onClick={scrollToBottom}
111
- aria-label="Scroll to bottom"
112
- >
113
- <i className="pi pi-arrow-down" />
114
- </button>
115
- </div>
116
- )}
117
- </div>
118
- );
119
- };
@@ -1,10 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import React from 'react';
5
- import * as Comp from './Properties';
6
- const Component: React.ComponentType<any> | undefined = (Comp as any).default || (Object.values(Comp)[0] as any);
7
-
8
- export default { title: 'TimeMachine/Properties', component: Component };
9
-
10
- export const Default = () => (Component ? <Component /> : <div>Unable to render component</div>);