@terraware/web-components 5.0.27-rc.0 → 5.0.27

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 (295) hide show
  1. package/components/AntSwitch/index.js +22 -19
  2. package/components/Autocomplete/Autocomplete.js +130 -106
  3. package/components/Badge/index.js +29 -28
  4. package/components/BusySpinner/index.js +45 -40
  5. package/components/Button/Button.js +47 -41
  6. package/components/Checkbox.js +63 -64
  7. package/components/Confirm/index.js +83 -74
  8. package/components/DatePicker/DatePicker.js +141 -138
  9. package/components/DialogBox/DialogBox.js +118 -111
  10. package/components/Divisor.js +18 -18
  11. package/components/Dropdown.js +94 -66
  12. package/components/EditableTable/index.js +271 -211
  13. package/components/ErrorBox/ErrorBox.js +49 -47
  14. package/components/FileChooser/index.js +135 -117
  15. package/components/FormBottomBar/index.js +84 -75
  16. package/components/Icon/Icon.js +20 -12
  17. package/components/Icon/icons/index.js +256 -256
  18. package/components/IconTooltip/index.js +60 -49
  19. package/components/Map/MapBox.js +452 -545
  20. package/components/Map/MapContainer.js +29 -25
  21. package/components/Map/MapDateSliderControl.js +64 -64
  22. package/components/Map/MapDrawer.js +47 -41
  23. package/components/Map/MapLegend.js +172 -176
  24. package/components/Map/MapViewStyleControl.js +63 -59
  25. package/components/Map/ReactMapboxWrapper.js +2 -3
  26. package/components/Map/index.js +180 -161
  27. package/components/Map/types.js +17 -12
  28. package/components/Map/useMaintainLayerOrder.js +26 -16
  29. package/components/Markdown/index.js +26 -25
  30. package/components/Message/Message.js +76 -73
  31. package/components/MultiSelect/index.js +124 -112
  32. package/components/Navbar/NavFooter.js +13 -9
  33. package/components/Navbar/NavItem.js +76 -70
  34. package/components/Navbar/NavSection.js +19 -17
  35. package/components/Navbar/Navbar.js +46 -39
  36. package/components/Navbar/SubNavbar.js +13 -9
  37. package/components/Note.js +22 -18
  38. package/components/OverlayModal/OverlayModal.js +63 -56
  39. package/components/PageForm/index.js +41 -33
  40. package/components/PhotoChooser/index.js +173 -165
  41. package/components/PhotosCarousel/PhotoSlide.js +35 -32
  42. package/components/PhotosCarousel/index.js +85 -80
  43. package/components/PhotosCarousel/usePhotosCarousel.js +76 -69
  44. package/components/Pill/index.js +45 -41
  45. package/components/PillList/index.js +24 -17
  46. package/components/PlacementWrapper/index.js +59 -38
  47. package/components/PopoverMenu/Popover.js +85 -68
  48. package/components/PopoverMenu/index.js +56 -51
  49. package/components/PopoverMultiSelect/index.js +59 -52
  50. package/components/ProgressCircle/ProgressCircle.js +32 -28
  51. package/components/RadioButton.js +19 -17
  52. package/components/Select/Select.js +15 -13
  53. package/components/Select/SelectT.js +250 -235
  54. package/components/Separator/index.js +17 -14
  55. package/components/Size.js +1 -0
  56. package/components/Slider/index.js +56 -43
  57. package/components/SummaryBox.js +72 -70
  58. package/components/Tabs/index.js +135 -133
  59. package/components/TextTruncated/index.js +130 -117
  60. package/components/Textfield/Textfield.js +190 -158
  61. package/components/Textfield/TruncatedTextArea.js +84 -70
  62. package/components/TimelineSlider/TimelineMarker.js +30 -25
  63. package/components/TimelineSlider/TimelineRail.js +11 -8
  64. package/components/TimelineSlider/index.js +66 -64
  65. package/components/TimelineSliderV2/ClusterBadge.js +29 -25
  66. package/components/TimelineSliderV2/TimelineDot.js +35 -31
  67. package/components/TimelineSliderV2/TimelineRail.js +11 -8
  68. package/components/TimelineSliderV2/index.js +103 -121
  69. package/components/TimelineSliderV2/layout.js +147 -124
  70. package/components/TimelineSliderV2/types.js +1 -0
  71. package/components/Tooltip/Tooltip.js +56 -47
  72. package/components/ViewPhotosDialog/index.js +35 -28
  73. package/components/VirtualWalkthrough/Annotation.js +207 -163
  74. package/components/VirtualWalkthrough/AnnotationEditPane.js +184 -198
  75. package/components/VirtualWalkthrough/AnnotationPanel.js +199 -187
  76. package/components/VirtualWalkthrough/Application.js +34 -31
  77. package/components/VirtualWalkthrough/AutoRotator.js +223 -85
  78. package/components/VirtualWalkthrough/BlockingSpinner.js +28 -26
  79. package/components/VirtualWalkthrough/BoundaryRing.js +34 -30
  80. package/components/VirtualWalkthrough/BoundaryWall.js +36 -32
  81. package/components/VirtualWalkthrough/CameraInfo.js +89 -100
  82. package/components/VirtualWalkthrough/ControlsInfoPane.js +195 -254
  83. package/components/VirtualWalkthrough/GradientSky.js +73 -72
  84. package/components/VirtualWalkthrough/SplatControls.js +221 -209
  85. package/components/VirtualWalkthrough/SplatCrop.js +20 -21
  86. package/components/VirtualWalkthrough/SplatFadeCrop.js +20 -21
  87. package/components/VirtualWalkthrough/SplatModel.js +85 -65
  88. package/components/VirtualWalkthrough/SplatRevealRain.js +46 -41
  89. package/components/VirtualWalkthrough/TfAnnotationManager.js +379 -197
  90. package/components/VirtualWalkthrough/TfXrNavigation.js +162 -73
  91. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +431 -438
  92. package/components/VirtualWalkthrough/VrAnnotationPanel.js +22 -18
  93. package/components/VirtualWalkthrough/XrAnnotationInteraction.js +17 -14
  94. package/components/VirtualWalkthrough/XrExitButton.js +17 -14
  95. package/components/VirtualWalkthrough/XrGazeDwell.js +17 -14
  96. package/components/VirtualWalkthrough/XrPointerRay.js +17 -14
  97. package/components/VirtualWalkthrough/XrStartPose.js +121 -67
  98. package/components/VirtualWalkthrough/boundary-ring.js +117 -87
  99. package/components/VirtualWalkthrough/boundary-wall.js +258 -175
  100. package/components/VirtualWalkthrough/camera-adoption.js +64 -18
  101. package/components/VirtualWalkthrough/groundPlane.js +47 -32
  102. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +35 -35
  103. package/components/VirtualWalkthrough/splatFormat.js +47 -13
  104. package/components/VirtualWalkthrough/useAdoptedCamera.js +44 -23
  105. package/components/VirtualWalkthrough/useRestartOnVr.js +37 -26
  106. package/components/VirtualWalkthrough/useXrRenderTuning.js +54 -33
  107. package/components/VirtualWalkthrough/vr-annotation-panel-layout.js +99 -67
  108. package/components/VirtualWalkthrough/vr-annotation-panel.js +433 -403
  109. package/components/VirtualWalkthrough/vr-annotation-scroll.js +28 -10
  110. package/components/VirtualWalkthrough/walkthrough-camera.js +329 -204
  111. package/components/VirtualWalkthrough/xr-annotation-candidate-buffer.js +80 -39
  112. package/components/VirtualWalkthrough/xr-annotation-candidates.js +18 -6
  113. package/components/VirtualWalkthrough/xr-annotation-interaction.js +56 -31
  114. package/components/VirtualWalkthrough/xr-annotation-targeting.js +38 -22
  115. package/components/VirtualWalkthrough/xr-button-arming.js +17 -7
  116. package/components/VirtualWalkthrough/xr-button-hold.js +36 -22
  117. package/components/VirtualWalkthrough/xr-exit-button-mask.js +36 -22
  118. package/components/VirtualWalkthrough/xr-exit-button.js +207 -148
  119. package/components/VirtualWalkthrough/xr-face-buttons.js +29 -19
  120. package/components/VirtualWalkthrough/xr-gaze-dwell-state.js +34 -23
  121. package/components/VirtualWalkthrough/xr-gaze-dwell.js +144 -107
  122. package/components/VirtualWalkthrough/xr-interactive-ui.js +24 -12
  123. package/components/VirtualWalkthrough/xr-pointer-ray.js +20 -13
  124. package/components/VirtualWalkthrough/xr-progress-pie-material.js +88 -117
  125. package/components/VirtualWalkthrough/xr-progress-pie.js +10 -1
  126. package/components/VirtualWalkthrough/xr-ray-quad.js +30 -16
  127. package/components/VirtualWalkthrough/xr-render-tuning.js +48 -17
  128. package/components/VirtualWalkthrough/xr-scene-bounds.js +37 -21
  129. package/components/VirtualWalkthrough/xr-start-pose.js +73 -27
  130. package/components/VirtualWalkthrough/xr-teleport-gesture.js +42 -16
  131. package/components/svg/BlobbyGrayIconImage.js +39 -41
  132. package/components/svg/BlobbyGrayIconImport.js +39 -41
  133. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +39 -41
  134. package/components/svg/BlobbyIconCloudChecked.js +164 -202
  135. package/components/svg/BlobbyIconExportOrUploadPhoto.js +164 -202
  136. package/components/svg/BlobbyIconFolder.js +164 -202
  137. package/components/svg/BlobbyIconGraphReport.js +164 -202
  138. package/components/svg/BlobbyIconHappy.js +164 -202
  139. package/components/svg/BlobbyIconHeartMonitor.js +164 -202
  140. package/components/svg/BlobbyIconLeaf.js +164 -202
  141. package/components/svg/BlobbyIconLibrary.js +164 -202
  142. package/components/svg/BlobbyIconNursery.js +166 -204
  143. package/components/svg/BlobbyIconOrganization.js +164 -202
  144. package/components/svg/BlobbyIconParchment.js +164 -202
  145. package/components/svg/BlobbyIconPeople.js +164 -202
  146. package/components/svg/BlobbyIconSeedBank.js +164 -202
  147. package/components/svg/BlobbyIconSeedling.js +164 -202
  148. package/components/svg/BlobbyIconSeeds.js +164 -202
  149. package/components/svg/BlobbyIconSite.js +167 -206
  150. package/components/svg/BlobbyIconSparkles.js +164 -202
  151. package/components/svg/BlobbyIconWrench.js +164 -202
  152. package/components/svg/Bug.js +21 -19
  153. package/components/svg/Calendar.js +21 -19
  154. package/components/svg/CaretDown.js +21 -19
  155. package/components/svg/CaretLeft.js +21 -19
  156. package/components/svg/CaretRight.js +21 -19
  157. package/components/svg/CaretUp.js +21 -19
  158. package/components/svg/ChevronDown.js +21 -19
  159. package/components/svg/ChevronUp.js +21 -19
  160. package/components/svg/Close.js +21 -19
  161. package/components/svg/Critical.js +21 -19
  162. package/components/svg/Edit.js +164 -202
  163. package/components/svg/Error.js +21 -19
  164. package/components/svg/Filter.js +21 -19
  165. package/components/svg/Folder.js +21 -19
  166. package/components/svg/Help.js +21 -19
  167. package/components/svg/Home.js +21 -19
  168. package/components/svg/IconAdd.js +21 -19
  169. package/components/svg/IconArrowRight.js +23 -21
  170. package/components/svg/IconBusinessNetwork.js +21 -19
  171. package/components/svg/IconCalendar.js +21 -19
  172. package/components/svg/IconCancel.js +21 -19
  173. package/components/svg/IconChargingBattery.js +21 -19
  174. package/components/svg/IconChecklist.js +23 -21
  175. package/components/svg/IconCheckmark.js +21 -19
  176. package/components/svg/IconCoinInHand.js +21 -19
  177. package/components/svg/IconColumns.js +21 -19
  178. package/components/svg/IconComment.js +22 -20
  179. package/components/svg/IconDashboard.js +21 -19
  180. package/components/svg/IconDataMigration.js +21 -19
  181. package/components/svg/IconDocument.js +23 -21
  182. package/components/svg/IconDownloadFromTheCloud.js +23 -21
  183. package/components/svg/IconEdit.js +23 -21
  184. package/components/svg/IconExpand.js +23 -21
  185. package/components/svg/IconExport.js +21 -19
  186. package/components/svg/IconExternalLink.js +21 -19
  187. package/components/svg/IconEye.js +21 -19
  188. package/components/svg/IconEyeOff.js +21 -19
  189. package/components/svg/IconFile.js +21 -19
  190. package/components/svg/IconFolder.js +21 -19
  191. package/components/svg/IconFullScreen.js +22 -20
  192. package/components/svg/IconFutures.js +21 -19
  193. package/components/svg/IconGraphReport.js +21 -19
  194. package/components/svg/IconGrid.js +21 -19
  195. package/components/svg/IconHeartMonitor.js +21 -19
  196. package/components/svg/IconHelp.js +23 -21
  197. package/components/svg/IconHistory.js +21 -19
  198. package/components/svg/IconImport.js +21 -19
  199. package/components/svg/IconIndex.js +21 -19
  200. package/components/svg/IconLayers.js +21 -19
  201. package/components/svg/IconLibrary.js +22 -20
  202. package/components/svg/IconList.js +21 -19
  203. package/components/svg/IconLivePlant.js +21 -19
  204. package/components/svg/IconLocations.js +21 -19
  205. package/components/svg/IconMail.js +21 -19
  206. package/components/svg/IconManager.js +21 -19
  207. package/components/svg/IconMap.js +21 -19
  208. package/components/svg/IconMarker.js +21 -19
  209. package/components/svg/IconMenu.js +21 -19
  210. package/components/svg/IconMenuHorizontal.js +21 -19
  211. package/components/svg/IconModule.js +21 -19
  212. package/components/svg/IconMyLocation.js +21 -19
  213. package/components/svg/IconNote.js +23 -21
  214. package/components/svg/IconNursery.js +23 -21
  215. package/components/svg/IconOrg.js +21 -19
  216. package/components/svg/IconParchment.js +21 -19
  217. package/components/svg/IconPhoto.js +21 -19
  218. package/components/svg/IconPlantsFilled.js +21 -19
  219. package/components/svg/IconRedo.js +21 -19
  220. package/components/svg/IconRestorationSite.js +21 -19
  221. package/components/svg/IconSeedBank.js +21 -19
  222. package/components/svg/IconSeedling.js +21 -19
  223. package/components/svg/IconSettings.js +21 -19
  224. package/components/svg/IconSlice.js +21 -19
  225. package/components/svg/IconSubmit.js +21 -19
  226. package/components/svg/IconSubtract.js +23 -21
  227. package/components/svg/IconSynced.js +21 -19
  228. package/components/svg/IconTrashCan.js +21 -19
  229. package/components/svg/IconTreasureMap.js +21 -19
  230. package/components/svg/IconUnavailable.js +21 -19
  231. package/components/svg/IconUndo.js +21 -19
  232. package/components/svg/IconVariable.js +21 -19
  233. package/components/svg/IconVideo.js +31 -30
  234. package/components/svg/IconWifi.js +21 -19
  235. package/components/svg/Info.js +21 -19
  236. package/components/svg/Key.js +21 -19
  237. package/components/svg/Leaf.js +21 -19
  238. package/components/svg/Lock.js +21 -19
  239. package/components/svg/Logo.js +43 -48
  240. package/components/svg/MenuVertical.js +21 -19
  241. package/components/svg/Notification.js +21 -19
  242. package/components/svg/Person.js +21 -19
  243. package/components/svg/Plus.js +21 -19
  244. package/components/svg/RestorationSite.js +21 -19
  245. package/components/svg/Search.js +21 -19
  246. package/components/svg/Seeds.js +21 -19
  247. package/components/svg/Site.js +21 -19
  248. package/components/svg/Sparkles.js +21 -19
  249. package/components/svg/Species.js +21 -19
  250. package/components/svg/Species2.js +164 -202
  251. package/components/svg/Spinner.js +48 -54
  252. package/components/svg/Star.js +21 -19
  253. package/components/svg/Success.js +21 -19
  254. package/components/svg/SuccessFilled.js +21 -19
  255. package/components/svg/TerrawareLogoDesktop.js +49 -55
  256. package/components/svg/TerrawareLogoMobile.js +26 -25
  257. package/components/svg/Touchscreen.js +21 -19
  258. package/components/svg/UploadCloud.js +164 -202
  259. package/components/svg/Warning.js +21 -19
  260. package/components/svg/WelcomeClipboard.js +133 -156
  261. package/components/svg/index.js +129 -129
  262. package/components/table/EnhancedTableToolbar.js +74 -68
  263. package/components/table/EnhancedTableToolbarV2.js +41 -31
  264. package/components/table/TableCellRenderer.js +231 -196
  265. package/components/table/TableHeader.js +73 -71
  266. package/components/table/TableHeaderItem.js +102 -97
  267. package/components/table/density.js +19 -18
  268. package/components/table/index.js +369 -350
  269. package/components/table/sort.js +52 -27
  270. package/components/table/types.js +1 -0
  271. package/components/types/index.js +1 -0
  272. package/hooks/cameraEntityContext.js +13 -2
  273. package/hooks/useBoolean.js +13 -17
  274. package/hooks/useCameraPosition.js +56 -56
  275. package/hooks/useDevicePerformance.js +17 -17
  276. package/hooks/useXr.js +87 -85
  277. package/index.js +58 -58
  278. package/package.json +1 -1
  279. package/setupTests.js +4 -0
  280. package/strings/export.js +170 -111
  281. package/strings/index.js +54 -25
  282. package/strings/locales.js +41 -21
  283. package/strings/strings-en.js +51 -49
  284. package/strings/strings-es.js +51 -49
  285. package/strings/strings-fr.js +51 -49
  286. package/strings/strings-gx.js +51 -49
  287. package/style-dictionary-dist/TerrawareTheme.js +186 -186
  288. package/theme.js +76 -74
  289. package/utils/color.js +15 -8
  290. package/utils/date.js +108 -42
  291. package/utils/index.js +4 -4
  292. package/utils/preventDefaultEvent.js +3 -3
  293. package/utils/text.js +11 -11
  294. package/utils/useDeviceInfo.js +79 -42
  295. package/virtualWalkthrough.js +23 -23
@@ -1,122 +1,104 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { useTheme } from "@mui/material";
4
- import ClusterBadge from "./ClusterBadge.js";
5
- import TimelineDot from "./TimelineDot.js";
6
- import TimelineRail from "./TimelineRail.js";
7
- import { DEFAULT_CLUSTER_THRESHOLD_PX, buildLayout } from "./layout.js";
8
- import "./styles.scss";
9
- const TimelineSliderV2 = ({ clusterThresholdPx = DEFAULT_CLUSTER_THRESHOLD_PX, labelEnd, labelStart, marks, onSelect, selectedMarkId })=>{
10
- const theme = useTheme();
11
- const containerRef = useRef(null);
12
- const [containerWidth, setContainerWidth] = useState(0);
13
- const [expandedClusterId, setExpandedClusterId] = useState();
14
- useEffect(()=>{
15
- const node = containerRef.current;
16
- if (null === node) return;
17
- const measure = ()=>setContainerWidth(node.clientWidth);
18
- measure();
19
- const observer = new ResizeObserver(measure);
20
- observer.observe(node);
21
- return ()=>observer.disconnect();
22
- }, []);
23
- const layout = useMemo(()=>buildLayout({
24
- containerWidth,
25
- expandedClusterId,
26
- marks,
27
- thresholdPx: clusterThresholdPx
28
- }), [
29
- clusterThresholdPx,
30
- containerWidth,
31
- expandedClusterId,
32
- marks
33
- ]);
34
- useEffect(()=>{
35
- if (containerWidth > 0 && void 0 !== expandedClusterId && void 0 === layout.band) setExpandedClusterId(void 0);
36
- }, [
37
- containerWidth,
38
- expandedClusterId,
39
- layout.band
40
- ]);
41
- const selectedLabel = useMemo(()=>marks.find((mark)=>mark.id === selectedMarkId)?.label, [
42
- marks,
43
- selectedMarkId
44
- ]);
45
- const markNames = useMemo(()=>new Map(marks.map((mark)=>[
46
- mark.id,
47
- mark.ariaLabel ?? mark.label
48
- ])), [
49
- marks
50
- ]);
51
- const nodeAriaLabel = useCallback((node)=>{
52
- const names = node.markIds.map((markId)=>markNames.get(markId)).filter((name)=>void 0 !== name);
53
- return names.length > 0 ? names.join(', ') : void 0;
54
- }, [
55
- markNames
56
- ]);
57
- const handleNodeClick = useCallback((node)=>{
58
- if (node.markIds.length > 1) setExpandedClusterId(node.id);
59
- else onSelect?.(node.markIds[0]);
60
- }, [
61
- onSelect
62
- ]);
63
- const handleCollapse = useCallback(()=>setExpandedClusterId(void 0), []);
64
- return /*#__PURE__*/ jsxs("div", {
65
- className: "timeline-v2",
66
- children: [
67
- /*#__PURE__*/ jsx("div", {
68
- className: "timeline-v2-label",
69
- style: {
70
- marginRight: theme.spacing(2)
71
- },
72
- children: labelStart
73
- }),
74
- /*#__PURE__*/ jsxs("div", {
75
- className: "timeline-v2-container",
76
- ref: containerRef,
77
- children: [
78
- /*#__PURE__*/ jsx(TimelineRail, {}),
79
- layout.band && /*#__PURE__*/ jsxs(Fragment, {
80
- children: [
81
- /*#__PURE__*/ jsx("div", {
82
- className: "timeline-v2-band",
83
- style: {
84
- left: `${layout.band.leftPx}px`,
85
- width: `${layout.band.widthPx}px`
86
- }
87
- }),
88
- /*#__PURE__*/ jsx(ClusterBadge, {
89
- count: layout.band.memberCount,
90
- leftPx: layout.band.leftPx + layout.band.widthPx / 2,
91
- onClose: handleCollapse
92
- })
93
- ]
94
- }),
95
- layout.nodes.map((node)=>/*#__PURE__*/ jsx(TimelineDot, {
96
- ariaLabel: nodeAriaLabel(node),
97
- colorWeights: node.colorWeights,
98
- dimmed: node.dimmed,
99
- leftPx: node.leftPx,
100
- markCount: node.markIds.length,
101
- onClick: ()=>handleNodeClick(node),
102
- selected: void 0 !== selectedMarkId && node.markIds.includes(selectedMarkId),
103
- sizePx: node.sizePx
104
- }, node.id))
105
- ]
106
- }),
107
- /*#__PURE__*/ jsx("div", {
108
- className: "timeline-v2-label",
109
- style: {
110
- marginLeft: theme.spacing(2)
111
- },
112
- children: labelEnd
113
- }),
114
- selectedLabel && /*#__PURE__*/ jsx("div", {
115
- className: "timeline-v2-selected-label",
116
- children: selectedLabel
117
- })
118
- ]
119
- });
1
+ import { useRef, useState, useEffect, useMemo, useCallback } from 'react';
2
+ import { useTheme } from '@mui/material';
3
+ import ClusterBadge from './ClusterBadge.js';
4
+ import TimelineDot from './TimelineDot.js';
5
+ import TimelineRail from './TimelineRail.js';
6
+ import { buildLayout, DEFAULT_CLUSTER_THRESHOLD_PX } from './layout.js';
7
+ import './styles.scss';
8
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+
10
+ const TimelineSliderV2 = ({
11
+ clusterThresholdPx = DEFAULT_CLUSTER_THRESHOLD_PX,
12
+ labelEnd,
13
+ labelStart,
14
+ marks,
15
+ onSelect,
16
+ selectedMarkId
17
+ }) => {
18
+ const theme = useTheme();
19
+ const containerRef = useRef(null);
20
+ const [containerWidth, setContainerWidth] = useState(0);
21
+ const [expandedClusterId, setExpandedClusterId] = useState();
22
+ useEffect(() => {
23
+ const node = containerRef.current;
24
+ if (node === null) {
25
+ return;
26
+ }
27
+ const measure = () => setContainerWidth(node.clientWidth);
28
+ measure();
29
+ const observer = new ResizeObserver(measure);
30
+ observer.observe(node);
31
+ return () => observer.disconnect();
32
+ }, []);
33
+ const layout = useMemo(() => buildLayout({
34
+ containerWidth,
35
+ expandedClusterId,
36
+ marks,
37
+ thresholdPx: clusterThresholdPx
38
+ }), [clusterThresholdPx, containerWidth, expandedClusterId, marks]);
39
+ useEffect(() => {
40
+ if (containerWidth > 0 && expandedClusterId !== undefined && layout.band === undefined) {
41
+ setExpandedClusterId(undefined);
42
+ }
43
+ }, [containerWidth, expandedClusterId, layout.band]);
44
+ const selectedLabel = useMemo(() => marks.find(mark => mark.id === selectedMarkId)?.label, [marks, selectedMarkId]);
45
+ const markNames = useMemo(() => new Map(marks.map(mark => [mark.id, mark.ariaLabel ?? mark.label])), [marks]);
46
+ const nodeAriaLabel = useCallback(node => {
47
+ const names = node.markIds.map(markId => markNames.get(markId)).filter(name => name !== undefined);
48
+ return names.length > 0 ? names.join(', ') : undefined;
49
+ }, [markNames]);
50
+ const handleNodeClick = useCallback(node => {
51
+ if (node.markIds.length > 1) {
52
+ setExpandedClusterId(node.id);
53
+ } else {
54
+ onSelect?.(node.markIds[0]);
55
+ }
56
+ }, [onSelect]);
57
+ const handleCollapse = useCallback(() => setExpandedClusterId(undefined), []);
58
+ return /*#__PURE__*/jsxs("div", {
59
+ className: "timeline-v2",
60
+ children: [/*#__PURE__*/jsx("div", {
61
+ className: "timeline-v2-label",
62
+ style: {
63
+ marginRight: theme.spacing(2)
64
+ },
65
+ children: labelStart
66
+ }), /*#__PURE__*/jsxs("div", {
67
+ className: "timeline-v2-container",
68
+ ref: containerRef,
69
+ children: [/*#__PURE__*/jsx(TimelineRail, {}), layout.band && /*#__PURE__*/jsxs(Fragment, {
70
+ children: [/*#__PURE__*/jsx("div", {
71
+ className: "timeline-v2-band",
72
+ style: {
73
+ left: `${layout.band.leftPx}px`,
74
+ width: `${layout.band.widthPx}px`
75
+ }
76
+ }), /*#__PURE__*/jsx(ClusterBadge, {
77
+ count: layout.band.memberCount,
78
+ leftPx: layout.band.leftPx + layout.band.widthPx / 2,
79
+ onClose: handleCollapse
80
+ })]
81
+ }), layout.nodes.map(node => /*#__PURE__*/jsx(TimelineDot, {
82
+ ariaLabel: nodeAriaLabel(node),
83
+ colorWeights: node.colorWeights,
84
+ dimmed: node.dimmed,
85
+ leftPx: node.leftPx,
86
+ markCount: node.markIds.length,
87
+ onClick: () => handleNodeClick(node),
88
+ selected: selectedMarkId !== undefined && node.markIds.includes(selectedMarkId),
89
+ sizePx: node.sizePx
90
+ }, node.id))]
91
+ }), /*#__PURE__*/jsx("div", {
92
+ className: "timeline-v2-label",
93
+ style: {
94
+ marginLeft: theme.spacing(2)
95
+ },
96
+ children: labelEnd
97
+ }), selectedLabel && /*#__PURE__*/jsx("div", {
98
+ className: "timeline-v2-selected-label",
99
+ children: selectedLabel
100
+ })]
101
+ });
120
102
  };
121
- const components_TimelineSliderV2 = TimelineSliderV2;
122
- export default components_TimelineSliderV2;
103
+
104
+ export { TimelineSliderV2 as default };
@@ -7,139 +7,162 @@ const SQUEEZE_GAP_PX = 12;
7
7
  const MAX_BAND_RATIO = 0.8;
8
8
  const DEFAULT_CLUSTER_THRESHOLD_PX = 16;
9
9
  const DIMMED_OPACITY = 0.35;
10
- const normalizePositions = (marks, containerWidth)=>{
11
- if (0 === marks.length) return [];
12
- const values = marks.map((mark)=>mark.value);
13
- const minValue = Math.min(...values);
14
- const maxValue = Math.max(...values);
15
- const range = maxValue - minValue;
16
- return marks.map((mark)=>({
17
- color: mark.color,
18
- id: mark.id,
19
- positionPx: (0 === range ? 1 : (mark.value - minValue) / range) * containerWidth
20
- })).sort((a, b)=>a.positionPx - b.positionPx);
10
+ const normalizePositions = (marks, containerWidth) => {
11
+ if (marks.length === 0) {
12
+ return [];
13
+ }
14
+ const values = marks.map(mark => mark.value);
15
+ const minValue = Math.min(...values);
16
+ const maxValue = Math.max(...values);
17
+ const range = maxValue - minValue;
18
+
19
+ // Mirrors TimelineSlider's behavior: when every mark shares one value, they all land at the right edge.
20
+ return marks.map(mark => ({
21
+ color: mark.color,
22
+ id: mark.id,
23
+ positionPx: (range === 0 ? 1 : (mark.value - minValue) / range) * containerWidth
24
+ })).sort((a, b) => a.positionPx - b.positionPx);
21
25
  };
22
- const toColorWeights = (colors)=>{
23
- const weights = new Map();
24
- colors.forEach((color)=>{
25
- weights.set(color, (weights.get(color) ?? 0) + 1);
26
- });
27
- return [
28
- ...weights.entries()
29
- ].map(([color, weight])=>({
30
- color,
31
- weight
32
- }));
26
+ const toColorWeights = colors => {
27
+ const weights = new Map();
28
+ colors.forEach(color => {
29
+ weights.set(color, (weights.get(color) ?? 0) + 1);
30
+ });
31
+ return [...weights.entries()].map(([color, weight]) => ({
32
+ color,
33
+ weight
34
+ }));
33
35
  };
34
- const buildClusters = (marks, containerWidth, thresholdPx)=>{
35
- const positioned = normalizePositions(marks, containerWidth);
36
- const clusters = [];
37
- let current = [];
38
- const flush = ()=>{
39
- if (0 === current.length) return;
40
- const total = current.reduce((sum, member)=>sum + member.positionPx, 0);
41
- clusters.push({
42
- anchorPx: total / current.length,
43
- id: `cluster-${current[0].id}`,
44
- members: current
45
- });
46
- current = [];
47
- };
48
- positioned.forEach((mark)=>{
49
- const previous = current[current.length - 1];
50
- if (void 0 !== previous && mark.positionPx - previous.positionPx >= thresholdPx) flush();
51
- current.push(mark);
36
+ const buildClusters = (marks, containerWidth, thresholdPx) => {
37
+ const positioned = normalizePositions(marks, containerWidth);
38
+ const clusters = [];
39
+ let current = [];
40
+ const flush = () => {
41
+ if (current.length === 0) {
42
+ return;
43
+ }
44
+ const total = current.reduce((sum, member) => sum + member.positionPx, 0);
45
+ clusters.push({
46
+ anchorPx: total / current.length,
47
+ id: `cluster-${current[0].id}`,
48
+ members: current
52
49
  });
53
- flush();
54
- return clusters;
50
+ current = [];
51
+ };
52
+ positioned.forEach(mark => {
53
+ const previous = current[current.length - 1];
54
+ if (previous !== undefined && mark.positionPx - previous.positionPx >= thresholdPx) {
55
+ flush();
56
+ }
57
+ current.push(mark);
58
+ });
59
+ flush();
60
+ return clusters;
55
61
  };
56
- const toConicGradient = (colorWeights)=>{
57
- if (colorWeights.length <= 1) return colorWeights[0]?.color ?? 'transparent';
58
- const total = colorWeights.reduce((sum, { weight })=>sum + weight, 0);
59
- let consumed = 0;
60
- const stops = colorWeights.map(({ color, weight })=>{
61
- const startDeg = consumed / total * 360;
62
- consumed += weight;
63
- const endDeg = consumed / total * 360;
64
- return `${color} ${startDeg}deg ${endDeg}deg`;
65
- });
66
- return `conic-gradient(${stops.join(', ')})`;
62
+ const toConicGradient = colorWeights => {
63
+ if (colorWeights.length <= 1) {
64
+ return colorWeights[0]?.color ?? 'transparent';
65
+ }
66
+ const total = colorWeights.reduce((sum, {
67
+ weight
68
+ }) => sum + weight, 0);
69
+ let consumed = 0;
70
+ const stops = colorWeights.map(({
71
+ color,
72
+ weight
73
+ }) => {
74
+ const startDeg = consumed / total * 360;
75
+ consumed += weight;
76
+ const endDeg = consumed / total * 360;
77
+ return `${color} ${startDeg}deg ${endDeg}deg`;
78
+ });
79
+ return `conic-gradient(${stops.join(', ')})`;
67
80
  };
68
- const toCollapsedNode = (cluster, dimmed)=>({
69
- colorWeights: toColorWeights(cluster.members.map((member)=>member.color)),
70
- dimmed,
71
- id: cluster.id,
72
- leftPx: cluster.anchorPx,
73
- markIds: cluster.members.map((member)=>member.id),
74
- sizePx: cluster.members.length > 1 ? CLUSTER_DOT_SIZE_PX : DOT_SIZE_PX
75
- });
76
- const clamp = (value, min, max)=>Math.min(Math.max(value, min), max);
77
- const expandedSpacing = (memberCount, containerWidth, maxBandWidth)=>{
78
- if (memberCount <= 1) return EXPANDED_SPACING_PX;
79
- const cap = Math.min(containerWidth * MAX_BAND_RATIO, maxBandWidth);
80
- const fitted = (cap - DOT_SIZE_PX - 2 * BAND_PADDING_PX) / (memberCount - 1);
81
- return Math.max(0, Math.min(EXPANDED_SPACING_PX, fitted));
81
+ const toCollapsedNode = (cluster, dimmed) => ({
82
+ colorWeights: toColorWeights(cluster.members.map(member => member.color)),
83
+ dimmed,
84
+ id: cluster.id,
85
+ leftPx: cluster.anchorPx,
86
+ markIds: cluster.members.map(member => member.id),
87
+ sizePx: cluster.members.length > 1 ? CLUSTER_DOT_SIZE_PX : DOT_SIZE_PX
88
+ });
89
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
90
+ const expandedSpacing = (memberCount, containerWidth, maxBandWidth) => {
91
+ if (memberCount <= 1) {
92
+ return EXPANDED_SPACING_PX;
93
+ }
94
+ const cap = Math.min(containerWidth * MAX_BAND_RATIO, maxBandWidth);
95
+ const fitted = (cap - DOT_SIZE_PX - 2 * BAND_PADDING_PX) / (memberCount - 1);
96
+ return Math.max(0, Math.min(EXPANDED_SPACING_PX, fitted));
82
97
  };
83
- const rescale = (value, fromStart, fromEnd, toStart, toEnd)=>{
84
- const fromSpan = fromEnd - fromStart;
85
- if (fromSpan <= 0) return toStart;
86
- return toStart + (value - fromStart) / fromSpan * (toEnd - toStart);
98
+ const rescale = (value, fromStart, fromEnd, toStart, toEnd) => {
99
+ const fromSpan = fromEnd - fromStart;
100
+ if (fromSpan <= 0) {
101
+ return toStart;
102
+ }
103
+ return toStart + (value - fromStart) / fromSpan * (toEnd - toStart);
87
104
  };
88
- const buildLayout = ({ containerWidth, expandedClusterId, marks, thresholdPx = DEFAULT_CLUSTER_THRESHOLD_PX })=>{
89
- if (containerWidth <= 0 || 0 === marks.length) return {
90
- nodes: []
91
- };
92
- const clusters = buildClusters(marks, containerWidth, thresholdPx);
93
- const expanded = clusters.find((cluster)=>cluster.id === expandedClusterId && cluster.members.length > 1);
94
- if (void 0 === expanded) return {
95
- nodes: clusters.map((cluster)=>toCollapsedNode(cluster, false))
96
- };
97
- const sideClusters = clusters.filter((cluster)=>cluster.id !== expanded.id);
98
- const leftCount = sideClusters.filter((cluster)=>cluster.anchorPx < expanded.anchorPx).length;
99
- const rightCount = sideClusters.length - leftCount;
100
- const reserve = (count)=>0 === count ? 0 : SQUEEZE_GAP_PX + (count - 1) * MIN_SQUEEZE_PITCH_PX;
101
- const leftReserve = reserve(leftCount);
102
- const rightReserve = reserve(rightCount);
103
- const minBandWidth = DOT_SIZE_PX + 2 * BAND_PADDING_PX;
104
- const maxBandWidth = Math.max(minBandWidth, containerWidth - leftReserve - rightReserve);
105
- const spacing = expandedSpacing(expanded.members.length, containerWidth, maxBandWidth);
106
- const widthPx = Math.min(maxBandWidth, (expanded.members.length - 1) * spacing + minBandWidth);
107
- const leftPx = clamp(expanded.anchorPx - widthPx / 2, leftReserve, Math.max(leftReserve, containerWidth - widthPx - rightReserve));
108
- const band = {
109
- leftPx,
110
- memberCount: expanded.members.length,
111
- widthPx
105
+ const buildLayout = ({
106
+ containerWidth,
107
+ expandedClusterId,
108
+ marks,
109
+ thresholdPx = DEFAULT_CLUSTER_THRESHOLD_PX
110
+ }) => {
111
+ if (containerWidth <= 0 || marks.length === 0) {
112
+ return {
113
+ nodes: []
112
114
  };
113
- const leftLimit = Math.max(0, leftPx - SQUEEZE_GAP_PX);
114
- const rightLimit = Math.min(containerWidth, leftPx + widthPx + SQUEEZE_GAP_PX);
115
- const nodes = clusters.flatMap((cluster)=>{
116
- if (cluster.id === expanded.id) return cluster.members.map((member, index)=>({
117
- colorWeights: [
118
- {
119
- color: member.color,
120
- weight: 1
121
- }
122
- ],
123
- dimmed: false,
124
- id: member.id,
125
- leftPx: leftPx + BAND_PADDING_PX + DOT_SIZE_PX / 2 + index * spacing,
126
- markIds: [
127
- member.id
128
- ],
129
- sizePx: DOT_SIZE_PX
130
- }));
131
- const collapsed = toCollapsedNode(cluster, true);
132
- const squeezed = cluster.anchorPx < expanded.anchorPx ? rescale(cluster.anchorPx, 0, expanded.anchorPx, 0, leftLimit) : rescale(cluster.anchorPx, expanded.anchorPx, containerWidth, rightLimit, containerWidth);
133
- return [
134
- {
135
- ...collapsed,
136
- leftPx: squeezed
137
- }
138
- ];
139
- });
115
+ }
116
+ const clusters = buildClusters(marks, containerWidth, thresholdPx);
117
+ const expanded = clusters.find(cluster => cluster.id === expandedClusterId && cluster.members.length > 1);
118
+ if (expanded === undefined) {
140
119
  return {
141
- band,
142
- nodes
120
+ nodes: clusters.map(cluster => toCollapsedNode(cluster, false))
143
121
  };
122
+ }
123
+ const sideClusters = clusters.filter(cluster => cluster.id !== expanded.id);
124
+ const leftCount = sideClusters.filter(cluster => cluster.anchorPx < expanded.anchorPx).length;
125
+ const rightCount = sideClusters.length - leftCount;
126
+ const reserve = count => count === 0 ? 0 : SQUEEZE_GAP_PX + (count - 1) * MIN_SQUEEZE_PITCH_PX;
127
+ const leftReserve = reserve(leftCount);
128
+ const rightReserve = reserve(rightCount);
129
+ const minBandWidth = DOT_SIZE_PX + 2 * BAND_PADDING_PX;
130
+ const maxBandWidth = Math.max(minBandWidth, containerWidth - leftReserve - rightReserve);
131
+ const spacing = expandedSpacing(expanded.members.length, containerWidth, maxBandWidth);
132
+ const widthPx = Math.min(maxBandWidth, (expanded.members.length - 1) * spacing + minBandWidth);
133
+ const leftPx = clamp(expanded.anchorPx - widthPx / 2, leftReserve, Math.max(leftReserve, containerWidth - widthPx - rightReserve));
134
+ const band = {
135
+ leftPx,
136
+ memberCount: expanded.members.length,
137
+ widthPx
138
+ };
139
+ const leftLimit = Math.max(0, leftPx - SQUEEZE_GAP_PX);
140
+ const rightLimit = Math.min(containerWidth, leftPx + widthPx + SQUEEZE_GAP_PX);
141
+ const nodes = clusters.flatMap(cluster => {
142
+ if (cluster.id === expanded.id) {
143
+ return cluster.members.map((member, index) => ({
144
+ colorWeights: [{
145
+ color: member.color,
146
+ weight: 1
147
+ }],
148
+ dimmed: false,
149
+ id: member.id,
150
+ leftPx: leftPx + BAND_PADDING_PX + DOT_SIZE_PX / 2 + index * spacing,
151
+ markIds: [member.id],
152
+ sizePx: DOT_SIZE_PX
153
+ }));
154
+ }
155
+ const collapsed = toCollapsedNode(cluster, true);
156
+ const squeezed = cluster.anchorPx < expanded.anchorPx ? rescale(cluster.anchorPx, 0, expanded.anchorPx, 0, leftLimit) : rescale(cluster.anchorPx, expanded.anchorPx, containerWidth, rightLimit, containerWidth);
157
+ return [{
158
+ ...collapsed,
159
+ leftPx: squeezed
160
+ }];
161
+ });
162
+ return {
163
+ band,
164
+ nodes
165
+ };
144
166
  };
167
+
145
168
  export { BAND_PADDING_PX, CLUSTER_DOT_SIZE_PX, DEFAULT_CLUSTER_THRESHOLD_PX, DIMMED_OPACITY, DOT_SIZE_PX, EXPANDED_SPACING_PX, MAX_BAND_RATIO, MIN_SQUEEZE_PITCH_PX, SQUEEZE_GAP_PX, buildClusters, buildLayout, normalizePositions, toColorWeights, toConicGradient };
@@ -0,0 +1 @@
1
+
@@ -1,48 +1,57 @@
1
- import { jsx } from "react/jsx-runtime";
2
- import react from "react";
3
- import { Tooltip, useTheme } from "@mui/material";
4
- import { useDeviceInfo } from "../../utils/index.js";
5
- function Tooltip_Tooltip({ children, placement = 'top-start', slotProps, sx, title }) {
6
- const [open, setOpen] = react.useState(false);
7
- const { isMobile } = useDeviceInfo();
8
- const theme = useTheme();
9
- const handleTooltipClose = ()=>{
10
- setOpen(false);
11
- };
12
- const handleTooltipOpen = (event)=>{
13
- if ('click' === event.type || 'mouseover' === event.type && !isMobile) setOpen(true);
14
- };
15
- return /*#__PURE__*/ jsx(Tooltip, {
16
- arrow: true,
17
- onOpen: handleTooltipOpen,
18
- onClose: handleTooltipClose,
19
- open: open,
20
- placement: placement,
21
- slotProps: slotProps,
22
- sx: [
23
- {
24
- maxWidth: isMobile ? '342px' : '464px',
25
- '& .MuiTooltip-arrow': {
26
- color: theme.palette.TwClrBaseGray800
27
- },
28
- '& .MuiTooltip-tooltip': {
29
- backgroundColor: theme.palette.TwClrBaseGray800,
30
- color: theme.palette.TwClrBaseWhite,
31
- padding: '8px',
32
- '& a': {
33
- color: theme.palette.TwClrBaseWhite
34
- }
35
- }
36
- },
37
- ...Array.isArray(sx) ? sx : [
38
- sx
39
- ]
40
- ],
41
- title: title,
42
- children: /*#__PURE__*/ jsx("span", {
43
- onClick: handleTooltipOpen,
44
- children: children
45
- })
46
- });
1
+ import React from 'react';
2
+ import { useTheme, Tooltip as Tooltip$1 } from '@mui/material';
3
+ import 'lodash';
4
+ import 'luxon';
5
+ import useDeviceInfo from '../../utils/useDeviceInfo.js';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ function Tooltip({
9
+ children,
10
+ placement = 'top-start',
11
+ slotProps,
12
+ sx,
13
+ title
14
+ }) {
15
+ const [open, setOpen] = React.useState(false);
16
+ const {
17
+ isMobile
18
+ } = useDeviceInfo();
19
+ const theme = useTheme();
20
+ const handleTooltipClose = () => {
21
+ setOpen(false);
22
+ };
23
+ const handleTooltipOpen = event => {
24
+ if (event.type === 'click' || event.type === 'mouseover' && !isMobile) {
25
+ setOpen(true);
26
+ }
27
+ };
28
+ return /*#__PURE__*/jsx(Tooltip$1, {
29
+ arrow: true,
30
+ onOpen: handleTooltipOpen,
31
+ onClose: handleTooltipClose,
32
+ open: open,
33
+ placement: placement,
34
+ slotProps: slotProps,
35
+ sx: [{
36
+ maxWidth: isMobile ? '342px' : '464px',
37
+ '& .MuiTooltip-arrow': {
38
+ color: theme.palette.TwClrBaseGray800
39
+ },
40
+ '& .MuiTooltip-tooltip': {
41
+ backgroundColor: theme.palette.TwClrBaseGray800,
42
+ color: theme.palette.TwClrBaseWhite,
43
+ padding: '8px',
44
+ '& a': {
45
+ color: theme.palette.TwClrBaseWhite
46
+ }
47
+ }
48
+ }, ...(Array.isArray(sx) ? sx : [sx])],
49
+ title: title,
50
+ children: /*#__PURE__*/jsx("span", {
51
+ onClick: handleTooltipOpen,
52
+ children: children
53
+ })
54
+ });
47
55
  }
48
- export default Tooltip_Tooltip;
56
+
57
+ export { Tooltip as default };