@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
@@ -0,0 +1,567 @@
1
+ /* Time Machine Container */
2
+ .time-machine {
3
+ position: relative;
4
+ width: 100%;
5
+ height: 100vh;
6
+ overflow: hidden;
7
+ background: radial-gradient(ellipse at center, #0a0a1a 0%, #000005 100%);
8
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
9
+ }
10
+
11
+ /* View Switcher */
12
+ .view-switcher {
13
+ position: absolute;
14
+ top: 20px;
15
+ left: 50%;
16
+ transform: translateX(-50%);
17
+ display: flex;
18
+ gap: 8px;
19
+ background: rgba(255, 255, 255, 0.05);
20
+ padding: 6px;
21
+ border-radius: 12px;
22
+ backdrop-filter: blur(10px);
23
+ border: 1px solid rgba(255, 255, 255, 0.1);
24
+ z-index: 100;
25
+ }
26
+
27
+ .view-button {
28
+ width: 48px;
29
+ height: 48px;
30
+ border: none;
31
+ border-radius: 8px;
32
+ background: transparent;
33
+ color: rgba(255, 255, 255, 0.6);
34
+ font-size: 20px;
35
+ cursor: pointer;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ transition: all 0.2s ease;
40
+ }
41
+
42
+ .view-button:hover {
43
+ background: rgba(255, 255, 255, 0.1);
44
+ color: rgba(255, 255, 255, 0.9);
45
+ }
46
+
47
+ .view-button.active {
48
+ background: rgba(100, 150, 255, 0.2);
49
+ color: rgba(100, 150, 255, 1);
50
+ box-shadow: 0 0 15px rgba(100, 150, 255, 0.3);
51
+ }
52
+
53
+ .view-button i {
54
+ font-size: 20px;
55
+ }
56
+
57
+
58
+ /* Starfield Background */
59
+ .time-machine-background {
60
+ position: absolute;
61
+ inset: 0;
62
+ overflow: hidden;
63
+ z-index: 0;
64
+ perspective: 500px;
65
+ perspective-origin: 50% 50%;
66
+ }
67
+
68
+ .stars {
69
+ position: absolute;
70
+ top: 50%;
71
+ left: 50%;
72
+ width: 2px;
73
+ height: 2px;
74
+ background: transparent;
75
+ transform-style: preserve-3d;
76
+ animation: starfield 16s linear infinite;
77
+ box-shadow:
78
+ /* Layer 1 - close stars */
79
+ 24vw -15vh 0 0px rgba(255,255,255,0.9),
80
+ -32vw 28vh 0 0px rgba(255,255,255,0.8),
81
+ 45vw 35vh 0 0px rgba(255,255,255,0.7),
82
+ -18vw -40vh 0 0px rgba(255,255,255,0.9),
83
+ 38vw -25vh 0 0px rgba(255,255,255,0.8),
84
+ -42vw 15vh 0 0px rgba(255,255,255,0.7),
85
+ 12vw 42vh 0 0px rgba(255,255,255,0.9),
86
+ -28vw -18vh 0 0px rgba(255,255,255,0.8),
87
+ 48vw 8vh 0 0px rgba(255,255,255,0.7),
88
+ -15vw 38vh 0 0px rgba(255,255,255,0.9),
89
+ 32vw -42vh 0 0px rgba(255,255,255,0.8),
90
+ -45vw -8vh 0 0px rgba(255,255,255,0.7),
91
+ 8vw -35vh 0 0px rgba(255,255,255,0.9),
92
+ -38vw 42vh 0 0px rgba(255,255,255,0.8),
93
+ 42vw 18vh 0 0px rgba(255,255,255,0.7),
94
+ -8vw -28vh 0 0px rgba(255,255,255,0.9),
95
+ 28vw 45vh 0 0px rgba(255,255,255,0.8),
96
+ -48vw 25vh 0 0px rgba(255,255,255,0.7),
97
+ 15vw -8vh 0 0px rgba(255,255,255,0.9),
98
+ -22vw 12vh 0 0px rgba(255,255,255,0.8);
99
+ }
100
+
101
+ .stars-2 {
102
+ animation: starfield 16s linear infinite;
103
+ animation-delay: -5.33s;
104
+ box-shadow:
105
+ /* Layer 2 - medium stars */
106
+ -12vw 22vh 0 0px rgba(255,255,255,0.9),
107
+ 35vw -32vh 0 0px rgba(255,255,255,0.8),
108
+ -40vw -15vh 0 0px rgba(255,255,255,0.7),
109
+ 22vw 40vh 0 0px rgba(255,255,255,0.9),
110
+ -25vw -35vh 0 0px rgba(255,255,255,0.8),
111
+ 40vw 12vh 0 0px rgba(255,255,255,0.7),
112
+ -35vw 32vh 0 0px rgba(255,255,255,0.9),
113
+ 18vw -22vh 0 0px rgba(255,255,255,0.8),
114
+ -10vw 45vh 0 0px rgba(255,255,255,0.7),
115
+ 45vw -10vh 0 0px rgba(255,255,255,0.9),
116
+ -30vw -42vh 0 0px rgba(255,255,255,0.8),
117
+ 5vw 30vh 0 0px rgba(255,255,255,0.7),
118
+ -45vw 5vh 0 0px rgba(255,255,255,0.9),
119
+ 30vw 22vh 0 0px rgba(255,255,255,0.8),
120
+ -20vw -12vh 0 0px rgba(255,255,255,0.7),
121
+ 48vw -38vh 0 0px rgba(255,255,255,0.9),
122
+ -5vw 18vh 0 0px rgba(255,255,255,0.8),
123
+ 25vw -45vh 0 0px rgba(255,255,255,0.7),
124
+ -48vw 38vh 0 0px rgba(255,255,255,0.9),
125
+ 10vw -5vh 0 0px rgba(255,255,255,0.8);
126
+ }
127
+
128
+ .stars-3 {
129
+ animation: starfield 16s linear infinite;
130
+ animation-delay: -10.66s;
131
+ box-shadow:
132
+ /* Layer 3 - far stars */
133
+ 18vw -28vh 0 0px rgba(255,255,255,0.9),
134
+ -28vw 35vh 0 0px rgba(255,255,255,0.8),
135
+ 42vw 25vh 0 0px rgba(255,255,255,0.7),
136
+ -15vw -45vh 0 0px rgba(255,255,255,0.9),
137
+ 35vw -18vh 0 0px rgba(255,255,255,0.8),
138
+ -42vw 8vh 0 0px rgba(255,255,255,0.7),
139
+ 8vw 48vh 0 0px rgba(255,255,255,0.9),
140
+ -35vw -25vh 0 0px rgba(255,255,255,0.8),
141
+ 48vw -5vh 0 0px rgba(255,255,255,0.7),
142
+ -8vw 28vh 0 0px rgba(255,255,255,0.9),
143
+ 25vw -48vh 0 0px rgba(255,255,255,0.8),
144
+ -48vw -18vh 0 0px rgba(255,255,255,0.7),
145
+ 5vw -38vh 0 0px rgba(255,255,255,0.9),
146
+ -25vw 48vh 0 0px rgba(255,255,255,0.8),
147
+ 38vw 5vh 0 0px rgba(255,255,255,0.7),
148
+ -18vw -32vh 0 0px rgba(255,255,255,0.9),
149
+ 32vw 38vh 0 0px rgba(255,255,255,0.8),
150
+ -38vw 18vh 0 0px rgba(255,255,255,0.7),
151
+ 12vw -15vh 0 0px rgba(255,255,255,0.9),
152
+ -32vw 5vh 0 0px rgba(255,255,255,0.8);
153
+ }
154
+
155
+ @keyframes starfield {
156
+ 0% {
157
+ transform: translateZ(-600px);
158
+ opacity: 0;
159
+ }
160
+ 5% {
161
+ opacity: 1;
162
+ }
163
+ 90% {
164
+ opacity: 1;
165
+ }
166
+ 100% {
167
+ transform: translateZ(500px);
168
+ opacity: 0;
169
+ }
170
+ }
171
+
172
+ /* Viewport for 3D Windows */
173
+ .time-machine-viewport {
174
+ position: absolute;
175
+ inset: 0;
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ perspective: 1200px;
180
+ perspective-origin: center 25%;
181
+ z-index: 1;
182
+ box-sizing: border-box;
183
+ }
184
+
185
+ .windows-container {
186
+ position: relative;
187
+ width: 60%;
188
+ max-width: 700px;
189
+ height: 55%;
190
+ max-height: 500px;
191
+ transform-style: preserve-3d;
192
+ }
193
+
194
+ /* Individual Version Window */
195
+ .version-window {
196
+ position: absolute;
197
+ inset: 0;
198
+ background: transparent;
199
+ overflow: visible;
200
+ cursor: pointer;
201
+ transform:
202
+ translateZ(calc(var(--z-offset) * 1px))
203
+ translateY(calc(var(--depth) * -35px))
204
+ scale(var(--scale));
205
+ opacity: var(--opacity);
206
+ transition:
207
+ transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
208
+ opacity 0.4s ease;
209
+ transform-style: preserve-3d;
210
+ will-change: transform, opacity;
211
+ perspective: 1500px;
212
+ }
213
+
214
+ .version-window-inner {
215
+ position: absolute;
216
+ inset: 0;
217
+ border-radius: 12px;
218
+ transform-style: preserve-3d;
219
+ transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
220
+ box-shadow:
221
+ 0 0 0 1px rgba(255, 255, 255, 0.1),
222
+ 0 20px 60px rgba(0, 0, 0, 0.5),
223
+ 0 0 40px rgba(100, 100, 255, 0.1);
224
+ }
225
+
226
+ .version-window.flipped .version-window-inner {
227
+ transform: rotateY(180deg);
228
+ }
229
+
230
+ .version-window-face {
231
+ position: absolute;
232
+ inset: 0;
233
+ display: flex;
234
+ flex-direction: column;
235
+ border-radius: inherit;
236
+ background: linear-gradient(180deg, #3a3a4a 0%, #2a2a3a 2%, #1e1e28 100%);
237
+ backface-visibility: hidden;
238
+ overflow: hidden;
239
+ pointer-events: auto;
240
+ }
241
+
242
+ .version-window-face--back {
243
+ transform: rotateY(180deg);
244
+ background: linear-gradient(180deg, #262638 0%, #1b1b27 100%);
245
+ }
246
+
247
+ .version-window.flipped .version-window-face--front {
248
+ pointer-events: none;
249
+ }
250
+
251
+ .version-window:not(.flipped) .version-window-face--back {
252
+ pointer-events: none;
253
+ }
254
+
255
+ .version-window.active .version-window-inner {
256
+ box-shadow:
257
+ 0 0 0 2px rgba(100, 150, 255, 0.5),
258
+ 0 20px 60px rgba(0, 0, 0, 0.5),
259
+ 0 0 60px rgba(100, 150, 255, 0.2);
260
+ }
261
+
262
+ .version-window:hover:not(.active) .version-window-inner {
263
+ box-shadow:
264
+ 0 0 0 1px rgba(255, 255, 255, 0.2),
265
+ 0 25px 70px rgba(0, 0, 0, 0.6),
266
+ 0 0 50px rgba(100, 100, 255, 0.15);
267
+ }
268
+
269
+ /* Window Chrome (Title Bar) */
270
+ .window-chrome {
271
+ display: grid;
272
+ grid-template-columns: auto 1fr auto;
273
+ align-items: center;
274
+ height: 36px;
275
+ padding: 0 12px;
276
+ background: linear-gradient(180deg, #4a4a5a 0%, #3a3a4a 100%);
277
+ border-bottom: 1px solid rgba(0, 0, 0, 0.3);
278
+ gap: 12px;
279
+ }
280
+
281
+ .window-controls {
282
+ display: flex;
283
+ gap: 8px;
284
+ }
285
+
286
+ .control {
287
+ width: 12px;
288
+ height: 12px;
289
+ border-radius: 50%;
290
+ background: #666;
291
+ }
292
+
293
+ .control.close {
294
+ background: #ff5f57;
295
+ }
296
+
297
+ .control.minimize {
298
+ background: #ffbd2e;
299
+ }
300
+
301
+ .control.maximize {
302
+ background: #28ca41;
303
+ }
304
+
305
+ .window-title {
306
+ text-align: center;
307
+ font-size: 13px;
308
+ font-weight: 500;
309
+ color: rgba(255, 255, 255, 0.85);
310
+ margin: 0;
311
+ }
312
+
313
+ .window-actions {
314
+ display: flex;
315
+ align-items: center;
316
+ justify-content: flex-end;
317
+ }
318
+
319
+ .window-flip-button {
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ width: 28px;
324
+ height: 28px;
325
+ border-radius: 6px;
326
+ border: 1px solid rgba(255, 255, 255, 0.15);
327
+ background: linear-gradient(180deg, rgba(120, 130, 220, 0.25) 0%, rgba(60, 70, 140, 0.25) 100%);
328
+ color: #fff;
329
+ cursor: pointer;
330
+ transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
331
+ }
332
+
333
+ .window-flip-button:hover {
334
+ transform: translateY(-1px);
335
+ box-shadow: 0 8px 18px rgba(0, 0, 0, 0.35);
336
+ border-color: rgba(120, 160, 255, 0.4);
337
+ }
338
+
339
+ .window-flip-button:active {
340
+ transform: translateY(0);
341
+ }
342
+
343
+ .window-flip-button:focus-visible {
344
+ outline: 2px solid rgba(120, 160, 255, 0.85);
345
+ outline-offset: 2px;
346
+ }
347
+
348
+ .window-flip-button i {
349
+ font-size: 14px;
350
+ }
351
+
352
+ .window-chrome--back {
353
+ background: linear-gradient(180deg, #35354a 0%, #2b2b3c 100%);
354
+ }
355
+
356
+ /* Window Content */
357
+ .window-content {
358
+ height: calc(100% - 36px);
359
+ padding: 20px;
360
+ overflow: auto;
361
+ background: linear-gradient(180deg, #1e1e28 0%, #16161e 100%);
362
+ color: #e0e0e0;
363
+ }
364
+
365
+ .window-content--events {
366
+ display: flex;
367
+ flex-direction: column;
368
+ gap: 1.5rem;
369
+ }
370
+
371
+ .snapshot-event-list {
372
+ display: flex;
373
+ flex-direction: column;
374
+ gap: 1.25rem;
375
+ }
376
+
377
+ .snapshot-event {
378
+ background: rgba(255, 255, 255, 0.05);
379
+ border: 1px solid rgba(255, 255, 255, 0.1);
380
+ border-radius: 10px;
381
+ padding: 1rem 1.25rem;
382
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
383
+ }
384
+
385
+ .snapshot-event-header {
386
+ display: flex;
387
+ align-items: baseline;
388
+ justify-content: space-between;
389
+ gap: 0.75rem;
390
+ margin-bottom: 0.75rem;
391
+ }
392
+
393
+ .snapshot-event-name {
394
+ font-size: 1rem;
395
+ font-weight: 600;
396
+ color: #ffffff;
397
+ }
398
+
399
+ .snapshot-event-timestamp {
400
+ font-size: 0.75rem;
401
+ color: rgba(255, 255, 255, 0.65);
402
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Mono', monospace;
403
+ }
404
+
405
+ /* Timeline */
406
+ .timeline {
407
+ position: absolute;
408
+ right: 20px;
409
+ top: 50%;
410
+ transform: translateY(-50%);
411
+ display: flex;
412
+ flex-direction: column;
413
+ justify-content: center;
414
+ z-index: 10;
415
+ }
416
+
417
+ .timeline-track {
418
+ display: flex;
419
+ flex-direction: column;
420
+ gap: 2px;
421
+ padding: 20px 0;
422
+ }
423
+
424
+ .timeline-track::-webkit-scrollbar {
425
+ display: none;
426
+ }
427
+
428
+ /* Timeline Entry */
429
+ .timeline-entry {
430
+ display: flex;
431
+ align-items: center;
432
+ justify-content: flex-end;
433
+ gap: 10px;
434
+ padding: 4px 0;
435
+ cursor: pointer;
436
+ transform-origin: right center;
437
+ transform: scale(var(--magnification, 1));
438
+ transition: transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);
439
+ }
440
+
441
+ .timeline-tick {
442
+ width: calc(20px * var(--magnification, 1));
443
+ height: calc(2px * var(--magnification, 1));
444
+ background: rgba(255, 255, 255, 0.4);
445
+ border-radius: 1px;
446
+ transition:
447
+ width 0.15s ease,
448
+ height 0.15s ease,
449
+ background 0.15s ease;
450
+ }
451
+
452
+ .timeline-entry.selected .timeline-tick {
453
+ background: #6a9fff;
454
+ box-shadow: 0 0 8px rgba(106, 159, 255, 0.6);
455
+ }
456
+
457
+ .timeline-entry.hovered .timeline-tick {
458
+ background: rgba(255, 255, 255, 0.9);
459
+ box-shadow: 0 0 6px rgba(255, 255, 255, 0.4);
460
+ }
461
+
462
+ .timeline-label {
463
+ display: flex;
464
+ flex-direction: column;
465
+ align-items: flex-end;
466
+ opacity: 0;
467
+ transform: translateX(10px);
468
+ transition:
469
+ opacity 0.2s ease,
470
+ transform 0.2s ease;
471
+ pointer-events: none;
472
+ white-space: nowrap;
473
+ }
474
+
475
+ .timeline-entry.hovered .timeline-label,
476
+ .timeline-entry.selected .timeline-label {
477
+ opacity: 1;
478
+ transform: translateX(0);
479
+ }
480
+
481
+ .timeline-date {
482
+ font-size: 11px;
483
+ font-weight: 600;
484
+ color: #fff;
485
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
486
+ }
487
+
488
+ .timeline-time {
489
+ font-size: 10px;
490
+ color: rgba(255, 255, 255, 0.7);
491
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
492
+ }
493
+
494
+ /* Navigation Controls */
495
+ .navigation-controls {
496
+ position: absolute;
497
+ bottom: 30px;
498
+ left: 50%;
499
+ transform: translateX(-50%);
500
+ display: flex;
501
+ gap: 20px;
502
+ z-index: 10;
503
+ }
504
+
505
+ .nav-button {
506
+ width: 60px;
507
+ height: 60px;
508
+ border: none;
509
+ border-radius: 50%;
510
+ background: linear-gradient(180deg, rgba(100, 100, 130, 0.8) 0%, rgba(60, 60, 90, 0.8) 100%);
511
+ color: white;
512
+ font-size: 28px;
513
+ font-weight: 300;
514
+ cursor: pointer;
515
+ display: flex;
516
+ align-items: center;
517
+ justify-content: center;
518
+ line-height: 1;
519
+ padding: 0;
520
+ box-shadow:
521
+ 0 4px 20px rgba(0, 0, 0, 0.4),
522
+ inset 0 1px 0 rgba(255, 255, 255, 0.2);
523
+ transition:
524
+ transform 0.2s ease,
525
+ box-shadow 0.2s ease,
526
+ opacity 0.2s ease;
527
+ backdrop-filter: blur(10px);
528
+ }
529
+
530
+ .nav-button:hover:not(:disabled) {
531
+ transform: scale(1.1);
532
+ box-shadow:
533
+ 0 6px 25px rgba(0, 0, 0, 0.5),
534
+ inset 0 1px 0 rgba(255, 255, 255, 0.3),
535
+ 0 0 20px rgba(100, 150, 255, 0.3);
536
+ }
537
+
538
+ .nav-button:active:not(:disabled) {
539
+ transform: scale(0.95);
540
+ }
541
+
542
+ .nav-button:disabled {
543
+ opacity: 0.3;
544
+ cursor: not-allowed;
545
+ }
546
+
547
+ /* Responsive adjustments */
548
+ @media (max-width: 768px) {
549
+ .time-machine-viewport {
550
+ width: calc(100% - 120px);
551
+ }
552
+
553
+ .timeline {
554
+ width: 100px;
555
+ }
556
+
557
+ .windows-container {
558
+ width: 85%;
559
+ height: 60%;
560
+ }
561
+
562
+ .nav-button {
563
+ width: 50px;
564
+ height: 50px;
565
+ font-size: 24px;
566
+ }
567
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"TimeMachine.d.ts","sourceRoot":"","sources":["../../../TimeMachine/TimeMachine.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,mBAAmB,CAAC;AAI3B,UAAU,gBAAgB;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAE1C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAkJlD,CAAC;AA8EF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"TimeMachine.d.ts","sourceRoot":"","sources":["../../../TimeMachine/TimeMachine.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,mBAAmB,CAAC;AAO3B,UAAU,gBAAgB;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAE1C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAkJlD,CAAC;AA8EF,eAAe,WAAW,CAAC"}
@@ -4,11 +4,16 @@ import { ReadModelView } from './ReadModelView.js';
4
4
  import { EventsView } from './EventsView.js';
5
5
  import './TimeMachine.css';
6
6
 
7
+ var ViewModes;
8
+ (function (ViewModes) {
9
+ ViewModes["ReadModel"] = "ReadModel";
10
+ ViewModes["Events"] = "Events";
11
+ })(ViewModes || (ViewModes = {}));
7
12
  const TimeMachine = ({ versions, currentVersionIndex = 0, onVersionChange, scrollSensitivity = 50, }) => {
8
13
  const [selectedIndex, setSelectedIndex] = useState(currentVersionIndex);
9
14
  const [hoveredIndex, setHoveredIndex] = useState(null);
10
15
  const [isHoveringCard, setIsHoveringCard] = useState(false);
11
- const [viewMode, setViewMode] = useState('readmodel');
16
+ const [viewMode, setViewMode] = useState(ViewModes.ReadModel);
12
17
  const containerRef = useRef(null);
13
18
  const scrollAccumulatorRef = useRef(0);
14
19
  const handleVersionSelect = useCallback((index) => {
@@ -19,7 +24,7 @@ const TimeMachine = ({ versions, currentVersionIndex = 0, onVersionChange, scrol
19
24
  setHoveredIndex(index);
20
25
  }, []);
21
26
  useEffect(() => {
22
- if (viewMode !== 'readmodel') {
27
+ if (viewMode !== ViewModes.ReadModel) {
23
28
  return;
24
29
  }
25
30
  const container = containerRef.current;
@@ -48,7 +53,7 @@ const TimeMachine = ({ versions, currentVersionIndex = 0, onVersionChange, scrol
48
53
  };
49
54
  }, [versions.length, selectedIndex, onVersionChange, scrollSensitivity, isHoveringCard, viewMode]);
50
55
  const allEvents = versions.flatMap(version => version.events || []);
51
- return (jsxs("div", { className: "time-machine", ref: containerRef, children: [jsxs("div", { className: "view-switcher", children: [jsx("button", { className: `view-button ${viewMode === 'readmodel' ? 'active' : ''}`, onClick: () => setViewMode('readmodel'), "aria-label": "Read Model View", title: "Read Model View", children: jsx("i", { className: "pi pi-box" }) }), jsx("button", { className: `view-button ${viewMode === 'events' ? 'active' : ''}`, onClick: () => setViewMode('events'), "aria-label": "Events View", title: "Events View", children: jsx("i", { className: "pi pi-list" }) })] }), viewMode === 'readmodel' ? (jsx(ReadModelView, { versions: versions, selectedIndex: selectedIndex, hoveredIndex: hoveredIndex, onVersionSelect: handleVersionSelect, onHoveringCardChange: setIsHoveringCard })) : (jsx(EventsView, { events: allEvents })), viewMode === 'readmodel' && (jsx(Timeline, { versions: versions, selectedIndex: selectedIndex, hoveredIndex: hoveredIndex, onSelect: handleVersionSelect, onHover: handleTimelineHover })), viewMode === 'readmodel' && (jsxs("div", { className: "navigation-controls", children: [jsx("button", { className: "nav-button prev", disabled: selectedIndex === 0, onClick: () => handleVersionSelect(Math.max(0, selectedIndex - 1)), "aria-label": "Previous version", children: "\u2039" }), jsx("button", { className: "nav-button next", disabled: selectedIndex === versions.length - 1, onClick: () => handleVersionSelect(Math.min(versions.length - 1, selectedIndex + 1)), "aria-label": "Next version", children: "\u203A" })] }))] }));
56
+ return (jsxs("div", { className: "time-machine", ref: containerRef, children: [jsxs("div", { className: "view-switcher", children: [jsx("button", { className: `view-button ${viewMode === ViewModes.ReadModel ? 'active' : ''}`, onClick: () => setViewMode(ViewModes.ReadModel), "aria-label": "Read Model View", title: "Read Model View", children: jsx("i", { className: "pi pi-box" }) }), jsx("button", { className: `view-button ${viewMode === ViewModes.Events ? 'active' : ''}`, onClick: () => setViewMode(ViewModes.Events), "aria-label": "Events View", title: "Events View", children: jsx("i", { className: "pi pi-list" }) })] }), viewMode === ViewModes.ReadModel ? (jsx(ReadModelView, { versions: versions, selectedIndex: selectedIndex, hoveredIndex: hoveredIndex, onVersionSelect: handleVersionSelect, onHoveringCardChange: setIsHoveringCard })) : (jsx(EventsView, { events: allEvents })), viewMode === ViewModes.ReadModel && (jsx(Timeline, { versions: versions, selectedIndex: selectedIndex, hoveredIndex: hoveredIndex, onSelect: handleVersionSelect, onHover: handleTimelineHover })), viewMode === ViewModes.ReadModel && (jsxs("div", { className: "navigation-controls", children: [jsx("button", { className: "nav-button prev", disabled: selectedIndex === 0, onClick: () => handleVersionSelect(Math.max(0, selectedIndex - 1)), "aria-label": "Previous version", children: "\u2039" }), jsx("button", { className: "nav-button next", disabled: selectedIndex === versions.length - 1, onClick: () => handleVersionSelect(Math.min(versions.length - 1, selectedIndex + 1)), "aria-label": "Next version", children: "\u203A" })] }))] }));
52
57
  };
53
58
  const Timeline = ({ versions, selectedIndex, hoveredIndex, onSelect, onHover, }) => {
54
59
  const getMagnification = (index, hoverIdx) => {
@@ -1 +1 @@
1
- {"version":3,"file":"TimeMachine.js","sources":["../../../TimeMachine/TimeMachine.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport type { Version } from './types';\nimport { ReadModelView } from './ReadModelView';\nimport { EventsView } from './EventsView';\nimport './TimeMachine.css';\n\ntype ViewMode = 'readmodel' | 'events';\n\ninterface TimeMachineProps {\n versions: Version[];\n currentVersionIndex?: number;\n onVersionChange?: (index: number) => void;\n /** Scroll sensitivity - higher values require more scrolling to change versions */\n scrollSensitivity?: number;\n}\n\nexport const TimeMachine: React.FC<TimeMachineProps> = ({\n versions,\n currentVersionIndex = 0,\n onVersionChange,\n scrollSensitivity = 50,\n}) => {\n const [selectedIndex, setSelectedIndex] = useState(currentVersionIndex);\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n const [isHoveringCard, setIsHoveringCard] = useState(false);\n const [viewMode, setViewMode] = useState<ViewMode>('readmodel');\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollAccumulatorRef = useRef(0);\n\n const handleVersionSelect = useCallback((index: number) => {\n setSelectedIndex(index);\n onVersionChange?.(index);\n }, [onVersionChange]);\n\n const handleTimelineHover = useCallback((index: number | null) => {\n setHoveredIndex(index);\n }, []);\n\n // Handle trackpad two-finger scroll gesture\n useEffect(() => {\n if (viewMode !== 'readmodel') {\n return;\n }\n\n const container = containerRef.current;\n if (!container) return;\n\n const handleWheel = (e: WheelEvent) => {\n // Only handle navigation when not hovering over a card\n if (isHoveringCard) {\n return; // Allow normal scrolling within cards\n }\n\n // Prevent default scrolling behavior\n e.preventDefault();\n\n // Use deltaX for horizontal scroll, fallback to deltaY for vertical\n // Most trackpads send horizontal delta for two-finger swipe\n const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;\n\n // Accumulate scroll delta\n scrollAccumulatorRef.current += delta;\n\n // Check if we've accumulated enough scroll to change version\n if (Math.abs(scrollAccumulatorRef.current) >= scrollSensitivity) {\n const direction = scrollAccumulatorRef.current > 0 ? 1 : -1;\n const newIndex = Math.max(0, Math.min(versions.length - 1, selectedIndex + direction));\n\n if (newIndex !== selectedIndex) {\n setSelectedIndex(newIndex);\n onVersionChange?.(newIndex);\n }\n\n // Reset accumulator after version change\n scrollAccumulatorRef.current = 0;\n }\n };\n\n container.addEventListener('wheel', handleWheel, { passive: false });\n\n return () => {\n container.removeEventListener('wheel', handleWheel);\n };\n }, [versions.length, selectedIndex, onVersionChange, scrollSensitivity, isHoveringCard, viewMode]);\n\n // Calculate the display index - either hovered or selected\n // (not used in this component; ReadModelView computes its own display index)\n void hoveredIndex;\n void selectedIndex;\n\n // Get all events from all versions\n const allEvents = versions.flatMap(version => version.events || []);\n\n return (\n <div className=\"time-machine\" ref={containerRef}>\n {/* View Switcher */}\n <div className=\"view-switcher\">\n <button\n className={`view-button ${viewMode === 'readmodel' ? 'active' : ''}`}\n onClick={() => setViewMode('readmodel')}\n aria-label=\"Read Model View\"\n title=\"Read Model View\"\n >\n <i className=\"pi pi-box\" />\n </button>\n <button\n className={`view-button ${viewMode === 'events' ? 'active' : ''}`}\n onClick={() => setViewMode('events')}\n aria-label=\"Events View\"\n title=\"Events View\"\n >\n <i className=\"pi pi-list\" />\n </button>\n </div>\n\n {/* Render the appropriate view */}\n {viewMode === 'readmodel' ? (\n <ReadModelView\n versions={versions}\n selectedIndex={selectedIndex}\n hoveredIndex={hoveredIndex}\n onVersionSelect={handleVersionSelect}\n onHoveringCardChange={setIsHoveringCard}\n />\n ) : (\n <EventsView events={allEvents} />\n )}\n\n {/* Timeline - only show in ReadModel view */}\n {viewMode === 'readmodel' && (\n <Timeline\n versions={versions}\n selectedIndex={selectedIndex}\n hoveredIndex={hoveredIndex}\n onSelect={handleVersionSelect}\n onHover={handleTimelineHover}\n />\n )}\n\n {/* Navigation arrows - only show in ReadModel view */}\n {viewMode === 'readmodel' && (\n <div className=\"navigation-controls\">\n <button\n className=\"nav-button prev\"\n disabled={selectedIndex === 0}\n onClick={() => handleVersionSelect(Math.max(0, selectedIndex - 1))}\n aria-label=\"Previous version\"\n >\n ‹\n </button>\n <button\n className=\"nav-button next\"\n disabled={selectedIndex === versions.length - 1}\n onClick={() => handleVersionSelect(Math.min(versions.length - 1, selectedIndex + 1))}\n aria-label=\"Next version\"\n >\n ›\n </button>\n </div>\n )}\n </div>\n );\n};\n\ninterface TimelineProps {\n versions: Version[];\n selectedIndex: number;\n hoveredIndex: number | null;\n onSelect: (index: number) => void;\n onHover: (index: number | null) => void;\n}\n\nconst Timeline: React.FC<TimelineProps> = ({\n versions,\n selectedIndex,\n hoveredIndex,\n onSelect,\n onHover,\n}) => {\n const getMagnification = (index: number, hoverIdx: number | null): number => {\n if (hoverIdx === null) return 1;\n const distance = Math.abs(index - hoverIdx);\n // Fish-eye effect: items close to hover get magnified\n if (distance === 0) return 2.0;\n if (distance === 1) return 1.6;\n if (distance === 2) return 1.3;\n if (distance === 3) return 1.1;\n return 1;\n };\n\n const formatDate = (date: Date): string => {\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n };\n\n const formatTime = (date: Date): string => {\n return date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n };\n\n return (\n <div\n className=\"timeline\"\n onMouseLeave={() => onHover(null)}\n >\n <div className=\"timeline-track\">\n {versions.map((version, index) => {\n const magnification = getMagnification(index, hoveredIndex);\n const isSelected = index === selectedIndex;\n const isHovered = index === hoveredIndex;\n\n return (\n <div\n key={version.id}\n className={`timeline-entry ${isSelected ? 'selected' : ''} ${isHovered ? 'hovered' : ''}`}\n style={{\n '--magnification': magnification,\n } as React.CSSProperties}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(index)}\n >\n <div className=\"timeline-tick\"></div>\n <div className=\"timeline-label\">\n <span className=\"timeline-date\">{formatDate(version.timestamp)}</span>\n <span className=\"timeline-time\">{formatTime(version.timestamp)}</span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default TimeMachine;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"TimeMachine.js","sources":["../../../TimeMachine/TimeMachine.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport type { Version } from './types';\nimport { ReadModelView } from './ReadModelView';\nimport { EventsView } from './EventsView';\nimport './TimeMachine.css';\n\nenum ViewModes {\n ReadModel = 'ReadModel',\n Events = 'Events',\n}\n\ninterface TimeMachineProps {\n versions: Version[];\n currentVersionIndex?: number;\n onVersionChange?: (index: number) => void;\n /** Scroll sensitivity - higher values require more scrolling to change versions */\n scrollSensitivity?: number;\n}\n\nexport const TimeMachine: React.FC<TimeMachineProps> = ({\n versions,\n currentVersionIndex = 0,\n onVersionChange,\n scrollSensitivity = 50,\n}) => {\n const [selectedIndex, setSelectedIndex] = useState(currentVersionIndex);\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n const [isHoveringCard, setIsHoveringCard] = useState(false);\n const [viewMode, setViewMode] = useState<ViewModes>(ViewModes.ReadModel);\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollAccumulatorRef = useRef(0);\n\n const handleVersionSelect = useCallback((index: number) => {\n setSelectedIndex(index);\n onVersionChange?.(index);\n }, [onVersionChange]);\n\n const handleTimelineHover = useCallback((index: number | null) => {\n setHoveredIndex(index);\n }, []);\n\n // Handle trackpad two-finger scroll gesture\n useEffect(() => {\n if (viewMode !== ViewModes.ReadModel) {\n return;\n }\n\n const container = containerRef.current;\n if (!container) return;\n\n const handleWheel = (e: WheelEvent) => {\n // Only handle navigation when not hovering over a card\n if (isHoveringCard) {\n return; // Allow normal scrolling within cards\n }\n\n // Prevent default scrolling behavior\n e.preventDefault();\n\n // Use deltaX for horizontal scroll, fallback to deltaY for vertical\n // Most trackpads send horizontal delta for two-finger swipe\n const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;\n\n // Accumulate scroll delta\n scrollAccumulatorRef.current += delta;\n\n // Check if we've accumulated enough scroll to change version\n if (Math.abs(scrollAccumulatorRef.current) >= scrollSensitivity) {\n const direction = scrollAccumulatorRef.current > 0 ? 1 : -1;\n const newIndex = Math.max(0, Math.min(versions.length - 1, selectedIndex + direction));\n\n if (newIndex !== selectedIndex) {\n setSelectedIndex(newIndex);\n onVersionChange?.(newIndex);\n }\n\n // Reset accumulator after version change\n scrollAccumulatorRef.current = 0;\n }\n };\n\n container.addEventListener('wheel', handleWheel, { passive: false });\n\n return () => {\n container.removeEventListener('wheel', handleWheel);\n };\n }, [versions.length, selectedIndex, onVersionChange, scrollSensitivity, isHoveringCard, viewMode]);\n\n // Calculate the display index - either hovered or selected\n // (not used in this component; ReadModelView computes its own display index)\n void hoveredIndex;\n void selectedIndex;\n\n // Get all events from all versions\n const allEvents = versions.flatMap(version => version.events || []);\n\n return (\n <div className=\"time-machine\" ref={containerRef}>\n {/* View Switcher */}\n <div className=\"view-switcher\">\n <button\n className={`view-button ${viewMode === ViewModes.ReadModel ? 'active' : ''}`}\n onClick={() => setViewMode(ViewModes.ReadModel)}\n aria-label=\"Read Model View\"\n title=\"Read Model View\"\n >\n <i className=\"pi pi-box\" />\n </button>\n <button\n className={`view-button ${viewMode === ViewModes.Events ? 'active' : ''}`}\n onClick={() => setViewMode(ViewModes.Events)}\n aria-label=\"Events View\"\n title=\"Events View\"\n >\n <i className=\"pi pi-list\" />\n </button>\n </div>\n\n {/* Render the appropriate view */}\n {viewMode === ViewModes.ReadModel ? (\n <ReadModelView\n versions={versions}\n selectedIndex={selectedIndex}\n hoveredIndex={hoveredIndex}\n onVersionSelect={handleVersionSelect}\n onHoveringCardChange={setIsHoveringCard}\n />\n ) : (\n <EventsView events={allEvents} />\n )}\n\n {/* Timeline - only show in ReadModel view */}\n {viewMode === ViewModes.ReadModel && (\n <Timeline\n versions={versions}\n selectedIndex={selectedIndex}\n hoveredIndex={hoveredIndex}\n onSelect={handleVersionSelect}\n onHover={handleTimelineHover}\n />\n )}\n\n {/* Navigation arrows - only show in ReadModel view */}\n {viewMode === ViewModes.ReadModel && (\n <div className=\"navigation-controls\">\n <button\n className=\"nav-button prev\"\n disabled={selectedIndex === 0}\n onClick={() => handleVersionSelect(Math.max(0, selectedIndex - 1))}\n aria-label=\"Previous version\"\n >\n ‹\n </button>\n <button\n className=\"nav-button next\"\n disabled={selectedIndex === versions.length - 1}\n onClick={() => handleVersionSelect(Math.min(versions.length - 1, selectedIndex + 1))}\n aria-label=\"Next version\"\n >\n ›\n </button>\n </div>\n )}\n </div>\n );\n};\n\ninterface TimelineProps {\n versions: Version[];\n selectedIndex: number;\n hoveredIndex: number | null;\n onSelect: (index: number) => void;\n onHover: (index: number | null) => void;\n}\n\nconst Timeline: React.FC<TimelineProps> = ({\n versions,\n selectedIndex,\n hoveredIndex,\n onSelect,\n onHover,\n}) => {\n const getMagnification = (index: number, hoverIdx: number | null): number => {\n if (hoverIdx === null) return 1;\n const distance = Math.abs(index - hoverIdx);\n // Fish-eye effect: items close to hover get magnified\n if (distance === 0) return 2.0;\n if (distance === 1) return 1.6;\n if (distance === 2) return 1.3;\n if (distance === 3) return 1.1;\n return 1;\n };\n\n const formatDate = (date: Date): string => {\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n };\n\n const formatTime = (date: Date): string => {\n return date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n };\n\n return (\n <div\n className=\"timeline\"\n onMouseLeave={() => onHover(null)}\n >\n <div className=\"timeline-track\">\n {versions.map((version, index) => {\n const magnification = getMagnification(index, hoveredIndex);\n const isSelected = index === selectedIndex;\n const isHovered = index === hoveredIndex;\n\n return (\n <div\n key={version.id}\n className={`timeline-entry ${isSelected ? 'selected' : ''} ${isHovered ? 'hovered' : ''}`}\n style={{\n '--magnification': magnification,\n } as React.CSSProperties}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(index)}\n >\n <div className=\"timeline-tick\"></div>\n <div className=\"timeline-label\">\n <span className=\"timeline-date\">{formatDate(version.timestamp)}</span>\n <span className=\"timeline-time\">{formatTime(version.timestamp)}</span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default TimeMachine;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}