@terraware/web-components 4.2.13 → 4.2.14-rc.1

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 (302) hide show
  1. package/components/AntSwitch/index.js +8 -14
  2. package/components/Autocomplete/Autocomplete.js +67 -70
  3. package/components/Badge/index.js +16 -20
  4. package/components/BusySpinner/index.js +30 -35
  5. package/components/Button/Button.js +23 -27
  6. package/components/Button/button.test.js +8 -10
  7. package/components/Checkbox.js +10 -19
  8. package/components/Confirm/index.js +44 -51
  9. package/components/DatePicker/DatePicker.js +116 -117
  10. package/components/DialogBox/DialogBox.js +76 -66
  11. package/components/Divisor.js +15 -20
  12. package/components/Dropdown.js +54 -61
  13. package/components/EditableTable/index.js +129 -135
  14. package/components/ErrorBox/ErrorBox.js +37 -36
  15. package/components/FileChooser/index.js +73 -77
  16. package/components/FormBottomBar/index.js +63 -69
  17. package/components/Icon/Icon.js +14 -21
  18. package/components/Icon/icons/index.js +251 -257
  19. package/components/IconTooltip/index.js +29 -34
  20. package/components/Map/MapBox.js +199 -220
  21. package/components/Map/MapContainer.js +14 -18
  22. package/components/Map/MapDateSliderControl.js +44 -46
  23. package/components/Map/MapDrawer.js +32 -33
  24. package/components/Map/MapLegend.js +96 -95
  25. package/components/Map/MapViewStyleControl.js +38 -48
  26. package/components/Map/ReactMapboxWrapper.js +2 -9
  27. package/components/Map/index.js +47 -55
  28. package/components/Map/types.js +2 -8
  29. package/components/Map/useMaintainLayerOrder.js +4 -11
  30. package/components/Markdown/index.js +14 -21
  31. package/components/Message/Message.js +59 -51
  32. package/components/MultiSelect/MultiSelect.test.js +22 -24
  33. package/components/MultiSelect/index.js +73 -69
  34. package/components/Navbar/NavFooter.js +8 -13
  35. package/components/Navbar/NavItem.js +43 -37
  36. package/components/Navbar/NavSection.js +13 -17
  37. package/components/Navbar/Navbar.js +35 -38
  38. package/components/Navbar/SubNavbar.js +8 -13
  39. package/components/Note.js +14 -19
  40. package/components/OverlayModal/OverlayModal.js +36 -37
  41. package/components/PageForm/index.js +30 -35
  42. package/components/PhotoChooser/index.js +93 -98
  43. package/components/Pill/index.js +29 -31
  44. package/components/PillList/index.js +16 -22
  45. package/components/PlacementWrapper/index.js +20 -25
  46. package/components/PopoverMenu/Popover.js +33 -37
  47. package/components/PopoverMenu/index.js +41 -46
  48. package/components/PopoverMultiSelect/index.js +18 -21
  49. package/components/ProgressCircle/ProgressCircle.js +23 -26
  50. package/components/RadioButton.js +7 -14
  51. package/components/Select/Select.js +8 -13
  52. package/components/Select/SelectT.js +110 -108
  53. package/components/Separator/index.js +8 -14
  54. package/components/Size.js +1 -5
  55. package/components/Slider/index.js +7 -13
  56. package/components/SummaryBox.js +36 -39
  57. package/components/Tabs/index.js +75 -77
  58. package/components/TextTruncated/index.js +64 -65
  59. package/components/Textfield/Textfield.js +100 -95
  60. package/components/Textfield/TruncatedTextArea.js +44 -46
  61. package/components/TimelineSlider/TimelineMarker.js +24 -28
  62. package/components/TimelineSlider/TimelineRail.js +5 -11
  63. package/components/TimelineSlider/index.js +47 -51
  64. package/components/Tooltip/Tooltip.js +21 -26
  65. package/components/ViewPhotosDialog/index.js +58 -62
  66. package/components/VirtualWalkthrough/Annotation.d.ts +41 -0
  67. package/components/VirtualWalkthrough/Annotation.d.ts.map +1 -0
  68. package/components/VirtualWalkthrough/Annotation.js +197 -0
  69. package/components/VirtualWalkthrough/AnnotationEditPane.d.ts +20 -0
  70. package/components/VirtualWalkthrough/AnnotationEditPane.d.ts.map +1 -0
  71. package/components/VirtualWalkthrough/AnnotationEditPane.js +136 -0
  72. package/components/VirtualWalkthrough/AnnotationPanel.d.ts +13 -0
  73. package/components/VirtualWalkthrough/AnnotationPanel.d.ts.map +1 -0
  74. package/components/VirtualWalkthrough/AnnotationPanel.js +196 -0
  75. package/components/VirtualWalkthrough/Application.d.ts +9 -0
  76. package/components/VirtualWalkthrough/Application.d.ts.map +1 -0
  77. package/components/VirtualWalkthrough/Application.js +32 -0
  78. package/components/VirtualWalkthrough/AutoRotator.d.ts +109 -0
  79. package/components/VirtualWalkthrough/AutoRotator.d.ts.map +1 -0
  80. package/components/VirtualWalkthrough/AutoRotator.js +217 -0
  81. package/components/VirtualWalkthrough/BlockingSpinner.d.ts +3 -0
  82. package/components/VirtualWalkthrough/BlockingSpinner.d.ts.map +1 -0
  83. package/components/VirtualWalkthrough/BlockingSpinner.js +27 -0
  84. package/components/VirtualWalkthrough/BoundaryRing.d.ts +9 -0
  85. package/components/VirtualWalkthrough/BoundaryRing.d.ts.map +1 -0
  86. package/components/VirtualWalkthrough/BoundaryRing.js +33 -0
  87. package/components/VirtualWalkthrough/CameraInfo.d.ts +16 -0
  88. package/components/VirtualWalkthrough/CameraInfo.d.ts.map +1 -0
  89. package/components/VirtualWalkthrough/CameraInfo.js +88 -0
  90. package/components/VirtualWalkthrough/ControlsInfoPane.d.ts +37 -0
  91. package/components/VirtualWalkthrough/ControlsInfoPane.d.ts.map +1 -0
  92. package/components/VirtualWalkthrough/ControlsInfoPane.js +196 -0
  93. package/components/VirtualWalkthrough/GradientSky.d.ts +9 -0
  94. package/components/VirtualWalkthrough/GradientSky.d.ts.map +1 -0
  95. package/components/VirtualWalkthrough/GradientSky.js +73 -0
  96. package/components/VirtualWalkthrough/SplatControls.d.ts +50 -0
  97. package/components/VirtualWalkthrough/SplatControls.d.ts.map +1 -0
  98. package/components/VirtualWalkthrough/SplatControls.js +252 -0
  99. package/components/VirtualWalkthrough/SplatCrop.d.ts +8 -0
  100. package/components/VirtualWalkthrough/SplatCrop.d.ts.map +1 -0
  101. package/components/VirtualWalkthrough/SplatCrop.js +18 -0
  102. package/components/VirtualWalkthrough/SplatFadeCrop.d.ts +8 -0
  103. package/components/VirtualWalkthrough/SplatFadeCrop.d.ts.map +1 -0
  104. package/components/VirtualWalkthrough/SplatFadeCrop.js +18 -0
  105. package/components/VirtualWalkthrough/SplatModel.d.ts +15 -0
  106. package/components/VirtualWalkthrough/SplatModel.d.ts.map +1 -0
  107. package/components/VirtualWalkthrough/SplatModel.js +60 -0
  108. package/components/VirtualWalkthrough/SplatRevealRain.d.ts +18 -0
  109. package/components/VirtualWalkthrough/SplatRevealRain.d.ts.map +1 -0
  110. package/components/VirtualWalkthrough/SplatRevealRain.js +38 -0
  111. package/components/VirtualWalkthrough/TfAnnotationManager.d.ts +110 -0
  112. package/components/VirtualWalkthrough/TfAnnotationManager.d.ts.map +1 -0
  113. package/components/VirtualWalkthrough/TfAnnotationManager.js +368 -0
  114. package/components/VirtualWalkthrough/TfXrNavigation.d.ts +15 -0
  115. package/components/VirtualWalkthrough/TfXrNavigation.d.ts.map +1 -0
  116. package/components/VirtualWalkthrough/TfXrNavigation.js +24 -0
  117. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.d.ts +27 -0
  118. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.d.ts.map +1 -0
  119. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +282 -0
  120. package/components/VirtualWalkthrough/annotation-styles.css +5 -0
  121. package/components/VirtualWalkthrough/application-styles.css +4 -0
  122. package/components/VirtualWalkthrough/boundary-ring.d.ts +47 -0
  123. package/components/VirtualWalkthrough/boundary-ring.d.ts.map +1 -0
  124. package/components/VirtualWalkthrough/boundary-ring.js +125 -0
  125. package/components/VirtualWalkthrough/boundary-ring.test.js +109 -0
  126. package/components/VirtualWalkthrough/groundPlane.d.ts +14 -0
  127. package/components/VirtualWalkthrough/groundPlane.d.ts.map +1 -0
  128. package/components/VirtualWalkthrough/groundPlane.js +47 -0
  129. package/components/VirtualWalkthrough/groundPlane.test.js +45 -0
  130. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.d.ts +19 -0
  131. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.d.ts.map +1 -0
  132. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +119 -0
  133. package/components/VirtualWalkthrough/walkthrough-camera.d.ts +77 -0
  134. package/components/VirtualWalkthrough/walkthrough-camera.d.ts.map +1 -0
  135. package/components/VirtualWalkthrough/walkthrough-camera.js +320 -0
  136. package/components/svg/BlobbyGrayIconImage.js +36 -41
  137. package/components/svg/BlobbyGrayIconImport.js +36 -41
  138. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +36 -41
  139. package/components/svg/BlobbyIconCloudChecked.js +161 -158
  140. package/components/svg/BlobbyIconExportOrUploadPhoto.js +161 -158
  141. package/components/svg/BlobbyIconFolder.js +161 -158
  142. package/components/svg/BlobbyIconGraphReport.js +161 -158
  143. package/components/svg/BlobbyIconHappy.js +161 -158
  144. package/components/svg/BlobbyIconHeartMonitor.js +161 -158
  145. package/components/svg/BlobbyIconLeaf.js +161 -158
  146. package/components/svg/BlobbyIconLibrary.js +161 -158
  147. package/components/svg/BlobbyIconNursery.js +163 -160
  148. package/components/svg/BlobbyIconOrganization.js +161 -158
  149. package/components/svg/BlobbyIconParchment.js +161 -158
  150. package/components/svg/BlobbyIconPeople.js +161 -158
  151. package/components/svg/BlobbyIconSeedBank.js +161 -158
  152. package/components/svg/BlobbyIconSeedling.js +161 -158
  153. package/components/svg/BlobbyIconSeeds.js +161 -158
  154. package/components/svg/BlobbyIconSite.js +164 -161
  155. package/components/svg/BlobbyIconSparkles.js +161 -158
  156. package/components/svg/BlobbyIconWrench.js +161 -158
  157. package/components/svg/Bug.js +18 -27
  158. package/components/svg/Calendar.js +18 -27
  159. package/components/svg/CaretDown.js +18 -27
  160. package/components/svg/CaretLeft.js +18 -27
  161. package/components/svg/CaretRight.js +18 -27
  162. package/components/svg/CaretUp.js +18 -27
  163. package/components/svg/ChevronDown.js +18 -27
  164. package/components/svg/ChevronUp.js +18 -27
  165. package/components/svg/Close.js +18 -27
  166. package/components/svg/Critical.js +18 -27
  167. package/components/svg/Edit.js +161 -158
  168. package/components/svg/Error.js +18 -27
  169. package/components/svg/Filter.js +18 -27
  170. package/components/svg/Folder.js +18 -27
  171. package/components/svg/Help.js +18 -27
  172. package/components/svg/Home.js +18 -27
  173. package/components/svg/IconAdd.js +18 -27
  174. package/components/svg/IconArrowRight.js +19 -28
  175. package/components/svg/IconBusinessNetwork.js +18 -27
  176. package/components/svg/IconCalendar.js +18 -27
  177. package/components/svg/IconCancel.js +18 -27
  178. package/components/svg/IconChargingBattery.js +18 -27
  179. package/components/svg/IconChecklist.js +19 -28
  180. package/components/svg/IconCheckmark.js +18 -27
  181. package/components/svg/IconCoinInHand.js +18 -27
  182. package/components/svg/IconColumns.js +18 -27
  183. package/components/svg/IconComment.js +18 -27
  184. package/components/svg/IconDashboard.js +18 -27
  185. package/components/svg/IconDataMigration.js +18 -27
  186. package/components/svg/IconDocument.js +19 -28
  187. package/components/svg/IconDownloadFromTheCloud.js +19 -28
  188. package/components/svg/IconEdit.js +19 -28
  189. package/components/svg/IconExpand.js +19 -28
  190. package/components/svg/IconExport.js +18 -27
  191. package/components/svg/IconExternalLink.js +18 -27
  192. package/components/svg/IconEye.js +18 -27
  193. package/components/svg/IconEyeOff.js +18 -27
  194. package/components/svg/IconFile.js +18 -27
  195. package/components/svg/IconFolder.js +18 -27
  196. package/components/svg/IconFullScreen.js +18 -27
  197. package/components/svg/IconFutures.js +18 -27
  198. package/components/svg/IconGraphReport.js +18 -27
  199. package/components/svg/IconHeartMonitor.js +18 -27
  200. package/components/svg/IconHelp.js +19 -28
  201. package/components/svg/IconHistory.js +18 -27
  202. package/components/svg/IconImport.js +18 -27
  203. package/components/svg/IconIndex.js +18 -27
  204. package/components/svg/IconLayers.js +18 -27
  205. package/components/svg/IconLibrary.js +18 -27
  206. package/components/svg/IconList.js +18 -27
  207. package/components/svg/IconLivePlant.js +18 -27
  208. package/components/svg/IconLocations.js +18 -27
  209. package/components/svg/IconMail.js +18 -27
  210. package/components/svg/IconManager.js +18 -27
  211. package/components/svg/IconMarker.js +18 -27
  212. package/components/svg/IconMenu.js +18 -27
  213. package/components/svg/IconMenuHorizontal.js +18 -27
  214. package/components/svg/IconModule.js +18 -27
  215. package/components/svg/IconMyLocation.js +18 -27
  216. package/components/svg/IconNote.js +19 -28
  217. package/components/svg/IconNursery.js +18 -27
  218. package/components/svg/IconOrg.js +18 -27
  219. package/components/svg/IconParchment.js +18 -27
  220. package/components/svg/IconPhoto.js +18 -27
  221. package/components/svg/IconPlantsFilled.js +18 -27
  222. package/components/svg/IconRedo.js +18 -27
  223. package/components/svg/IconRestorationSite.js +18 -27
  224. package/components/svg/IconSeedBank.js +18 -27
  225. package/components/svg/IconSeedling.js +18 -27
  226. package/components/svg/IconSettings.js +18 -27
  227. package/components/svg/IconSlice.js +18 -27
  228. package/components/svg/IconSubmit.js +18 -27
  229. package/components/svg/IconSubtract.js +19 -28
  230. package/components/svg/IconSynced.js +18 -27
  231. package/components/svg/IconTrashCan.js +18 -27
  232. package/components/svg/IconTreasureMap.js +18 -27
  233. package/components/svg/IconUnavailable.js +18 -27
  234. package/components/svg/IconUndo.js +18 -27
  235. package/components/svg/IconVariable.js +18 -27
  236. package/components/svg/IconVideo.js +19 -28
  237. package/components/svg/IconWifi.js +18 -27
  238. package/components/svg/Info.js +18 -27
  239. package/components/svg/Key.js +18 -27
  240. package/components/svg/Leaf.js +18 -27
  241. package/components/svg/Lock.js +18 -27
  242. package/components/svg/Logo.js +40 -45
  243. package/components/svg/MenuVertical.js +18 -27
  244. package/components/svg/Notification.js +18 -27
  245. package/components/svg/Person.js +18 -27
  246. package/components/svg/Plus.js +18 -27
  247. package/components/svg/RestorationSite.js +18 -27
  248. package/components/svg/Search.js +18 -27
  249. package/components/svg/Seeds.js +18 -27
  250. package/components/svg/Site.js +18 -27
  251. package/components/svg/Sparkles.js +18 -27
  252. package/components/svg/Species.js +18 -27
  253. package/components/svg/Species2.js +161 -158
  254. package/components/svg/Spinner.js +27 -36
  255. package/components/svg/Star.js +18 -27
  256. package/components/svg/Success.js +18 -27
  257. package/components/svg/SuccessFilled.js +18 -27
  258. package/components/svg/TerrawareLogoDesktop.js +44 -49
  259. package/components/svg/TerrawareLogoMobile.js +20 -29
  260. package/components/svg/Touchscreen.js +18 -27
  261. package/components/svg/UploadCloud.js +161 -158
  262. package/components/svg/Warning.js +18 -27
  263. package/components/svg/WelcomeClipboard.js +130 -135
  264. package/components/svg/index.js +127 -895
  265. package/components/table/EnhancedTableToolbar.js +45 -47
  266. package/components/table/EnhancedTableToolbarV2.js +18 -26
  267. package/components/table/TableCellRenderer.js +137 -143
  268. package/components/table/TableHeader.js +45 -47
  269. package/components/table/TableHeaderItem.js +65 -64
  270. package/components/table/density.js +3 -11
  271. package/components/table/index.js +225 -218
  272. package/components/table/sort.js +8 -18
  273. package/components/table/sort.test.js +6 -8
  274. package/components/table/types.js +1 -5
  275. package/components/types/index.js +1 -5
  276. package/hooks/useBoolean.d.ts +4 -0
  277. package/hooks/useBoolean.d.ts.map +1 -0
  278. package/hooks/useBoolean.js +12 -0
  279. package/hooks/useCameraPosition.d.ts +8 -0
  280. package/hooks/useCameraPosition.d.ts.map +1 -0
  281. package/hooks/useCameraPosition.js +33 -0
  282. package/hooks/useDevicePerformance.d.ts +9 -0
  283. package/hooks/useDevicePerformance.d.ts.map +1 -0
  284. package/hooks/useDevicePerformance.js +16 -0
  285. package/index.js +57 -398
  286. package/license-report.html +1 -1
  287. package/package.json +10 -3
  288. package/style-dictionary-dist/TerrawareTheme.js +1 -7
  289. package/theme.js +7 -14
  290. package/utils/color.d.ts +2 -0
  291. package/utils/color.d.ts.map +1 -0
  292. package/utils/color.js +14 -0
  293. package/utils/date.js +13 -24
  294. package/utils/date.test.js +40 -43
  295. package/utils/index.js +5 -53
  296. package/utils/preventDefaultEvent.js +1 -7
  297. package/utils/text.js +2 -9
  298. package/utils/text.test.js +9 -11
  299. package/utils/useDeviceInfo.js +10 -16
  300. package/virtualWalkthrough.d.ts +34 -0
  301. package/virtualWalkthrough.d.ts.map +1 -0
  302. package/virtualWalkthrough.js +30 -0
@@ -0,0 +1,196 @@
1
+ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { useTheme } from '@mui/material';
3
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
+ // Fallback hotspot diameter (px) when the rendered size isn't reported yet.
5
+ const DEFAULT_HOTSPOT_DIAMETER = 35;
6
+
7
+ // Horizontal gap (px) kept between the panel's right edge and the hotspot so
8
+ // the connector line stays visible.
9
+ const PANEL_HOTSPOT_GAP = 48;
10
+
11
+ // Minimum distance from the left edge of the viewer, as a fraction of its
12
+ // width, so the panel never drifts further left than this.
13
+ const MIN_LEFT_FRACTION = 0.02;
14
+ const CONNECTOR_STYLE = {
15
+ position: 'absolute',
16
+ inset: 0,
17
+ width: '100%',
18
+ height: '100%',
19
+ pointerEvents: 'none',
20
+ overflow: 'visible',
21
+ zIndex: 5002
22
+ };
23
+ const PANEL_STYLE = {
24
+ position: 'absolute',
25
+ left: '2%',
26
+ top: '50%',
27
+ transform: 'translateY(-50%)',
28
+ maxHeight: '80vh',
29
+ zIndex: 5003,
30
+ backgroundColor: '#ffffff',
31
+ borderRadius: 12,
32
+ boxShadow: '0 8px 32px rgba(0,0,0,0.32)',
33
+ overflowY: 'auto',
34
+ display: 'flex',
35
+ flexDirection: 'column'
36
+ };
37
+ const IMAGE_STYLE = {
38
+ width: 'auto',
39
+ height: 'auto',
40
+ maxWidth: '100%',
41
+ maxHeight: '60vh',
42
+ display: 'block',
43
+ borderRadius: '12px 12px 0 0',
44
+ flexShrink: 0
45
+ };
46
+ const TEXT_BLOCK_STYLE = {
47
+ padding: '24px',
48
+ display: 'flex',
49
+ flexDirection: 'column',
50
+ gap: 8
51
+ };
52
+ const AnnotationPanel = ({
53
+ annotation,
54
+ hotspotPosition,
55
+ onClose
56
+ }) => {
57
+ const theme = useTheme();
58
+ const panelRef = useRef(null);
59
+ const connectorRef = useRef(null);
60
+ const [lineStart, setLineStart] = useState(null);
61
+ const [panelLeft, setPanelLeft] = useState(null);
62
+ useEffect(() => {
63
+ if (!annotation) {
64
+ return;
65
+ }
66
+ const handleKeyDown = e => {
67
+ if (e.key === 'Escape') {
68
+ onClose();
69
+ }
70
+ };
71
+ const handlePointerDown = e => {
72
+ if (panelRef.current && !panelRef.current.contains(e.target)) {
73
+ onClose();
74
+ }
75
+ };
76
+ document.addEventListener('keydown', handleKeyDown);
77
+ document.addEventListener('pointerdown', handlePointerDown);
78
+ return () => {
79
+ document.removeEventListener('keydown', handleKeyDown);
80
+ document.removeEventListener('pointerdown', handlePointerDown);
81
+ };
82
+ }, [annotation, onClose]);
83
+
84
+ // Position the panel just to the left of the hotspot (clamped so it never
85
+ // goes further left than MIN_LEFT_FRACTION of the viewer) and anchor the
86
+ // connector line at the vertical center of the panel's right edge, in the
87
+ // connector SVG's coordinate space.
88
+ useLayoutEffect(() => {
89
+ if (!annotation || !hotspotPosition || !panelRef.current || !connectorRef.current) {
90
+ // eslint-disable-next-line react-hooks/set-state-in-effect
91
+ setPanelLeft(null);
92
+ setLineStart(null);
93
+ return;
94
+ }
95
+ const panelWidth = panelRef.current.getBoundingClientRect().width;
96
+ const connectorRect = connectorRef.current.getBoundingClientRect();
97
+ const minLeft = connectorRect.width * MIN_LEFT_FRACTION;
98
+ const desiredLeft = hotspotPosition.x - PANEL_HOTSPOT_GAP - panelWidth;
99
+ const left = Math.max(desiredLeft, minLeft);
100
+ setPanelLeft(left);
101
+ setLineStart({
102
+ x: left + panelWidth,
103
+ y: connectorRect.height / 2
104
+ });
105
+ }, [annotation, hotspotPosition]);
106
+ if (!annotation) {
107
+ return null;
108
+ }
109
+ const panelStyle = {
110
+ ...PANEL_STYLE,
111
+ ...(annotation.imageUrl ? {
112
+ width: 'fit-content',
113
+ maxWidth: '60vw'
114
+ } : {
115
+ width: 'fit-content',
116
+ maxWidth: '50vw'
117
+ }),
118
+ ...(panelLeft !== null ? {
119
+ left: `${panelLeft}px`
120
+ } : {})
121
+ };
122
+
123
+ // Stop the line at the edge of the hotspot circle
124
+ let lineEnd = null;
125
+ if (lineStart && hotspotPosition) {
126
+ const dx = hotspotPosition.x - lineStart.x;
127
+ const dy = hotspotPosition.y - lineStart.y;
128
+ const dist = Math.hypot(dx, dy);
129
+ const radius = (hotspotPosition.size ?? DEFAULT_HOTSPOT_DIAMETER) / 2;
130
+ const t = dist > radius ? (dist - radius) / dist : 0;
131
+ lineEnd = {
132
+ x: lineStart.x + dx * t,
133
+ y: lineStart.y + dy * t
134
+ };
135
+ }
136
+ return /*#__PURE__*/_jsxs(_Fragment, {
137
+ children: [/*#__PURE__*/_jsx("svg", {
138
+ ref: connectorRef,
139
+ "data-testid": "annotation-panel-connector",
140
+ style: CONNECTOR_STYLE,
141
+ children: lineStart && lineEnd && /*#__PURE__*/_jsx("line", {
142
+ x1: lineStart.x,
143
+ y1: lineStart.y,
144
+ x2: lineEnd.x,
145
+ y2: lineEnd.y,
146
+ stroke: "#ffffff",
147
+ strokeWidth: 2
148
+ })
149
+ }), /*#__PURE__*/_jsxs("div", {
150
+ ref: panelRef,
151
+ "data-testid": "annotation-panel",
152
+ style: panelStyle,
153
+ children: [annotation.imageUrl && /*#__PURE__*/_jsx("img", {
154
+ src: annotation.imageUrl,
155
+ alt: annotation.title,
156
+ style: IMAGE_STYLE
157
+ }), /*#__PURE__*/_jsxs("div", {
158
+ style: TEXT_BLOCK_STYLE,
159
+ children: [annotation.label && /*#__PURE__*/_jsx("span", {
160
+ "data-testid": "annotation-panel-label",
161
+ style: {
162
+ alignSelf: 'flex-start',
163
+ fontSize: 14,
164
+ fontWeight: 500,
165
+ color: theme.palette.TwClrTxtSuccess,
166
+ margin: 0,
167
+ padding: theme.spacing(0.5, 1),
168
+ backgroundColor: theme.palette.TwClrBgSuccessTertiary,
169
+ border: `1px solid ${theme.palette.TwClrBrdrSuccess}`,
170
+ borderRadius: theme.spacing(1)
171
+ },
172
+ children: annotation.label
173
+ }), /*#__PURE__*/_jsx("h2", {
174
+ "data-testid": "annotation-panel-title",
175
+ style: {
176
+ fontSize: 32,
177
+ fontWeight: 600,
178
+ color: theme.palette.TwClrTxt,
179
+ margin: 0
180
+ },
181
+ children: annotation.title
182
+ }), annotation.bodyText && /*#__PURE__*/_jsx("p", {
183
+ "data-testid": "annotation-panel-description",
184
+ style: {
185
+ fontSize: 16,
186
+ color: theme.palette.TwClrTxt,
187
+ lineHeight: '24px',
188
+ margin: 0
189
+ },
190
+ children: annotation.bodyText
191
+ })]
192
+ })]
193
+ })]
194
+ });
195
+ };
196
+ export default AnnotationPanel;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import './application-styles.css';
3
+ interface ApplicationProps {
4
+ children: React.ReactNode;
5
+ style?: Record<string, unknown>;
6
+ }
7
+ declare const Application: ({ children, style }: ApplicationProps) => import("react/jsx-runtime").JSX.Element;
8
+ export default Application;
9
+ //# sourceMappingURL=Application.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/Application.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,0BAA0B,CAAC;AAElC,UAAU,gBAAgB;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,QAAA,MAAM,WAAW,GAAI,qBAAqB,gBAAgB,4CA2BzD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { Application as PcApplication } from '@playcanvas/react';
3
+ import './application-styles.css';
4
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
5
+ const Application = ({
6
+ children,
7
+ style
8
+ }) => {
9
+ return /*#__PURE__*/_jsxs(_Fragment, {
10
+ children: [/*#__PURE__*/_jsx(PcApplication, {
11
+ style: style,
12
+ graphicsDeviceOptions: {
13
+ antialias: false,
14
+ xrCompatible: true
15
+ },
16
+ children: children
17
+ }), /*#__PURE__*/_jsx("div", {
18
+ "data-annotation-container": true,
19
+ className: "annotation-container",
20
+ style: {
21
+ position: 'absolute',
22
+ top: 0,
23
+ left: 0,
24
+ width: '100%',
25
+ height: '100%',
26
+ pointerEvents: 'none',
27
+ zIndex: 1000
28
+ }
29
+ })]
30
+ });
31
+ };
32
+ export default Application;
@@ -0,0 +1,109 @@
1
+ import { Script } from 'playcanvas';
2
+ /**
3
+ * Auto-rotator script for PlayCanvas CameraControls.
4
+ * Automatically orbits the camera around its focus point after a period of inactivity.
5
+ */
6
+ export declare class AutoRotator extends Script {
7
+ static scriptName: string;
8
+ /**
9
+ * Rotation speed in degrees per second when auto-rotating.
10
+ *
11
+ * @attribute
12
+ * @title Speed
13
+ */
14
+ speed: number;
15
+ /**
16
+ * Delay in seconds before auto-rotation starts after initialization.
17
+ *
18
+ * @attribute
19
+ * @title Start Delay
20
+ */
21
+ startDelay: number;
22
+ /**
23
+ * Delay in seconds before auto-rotation restarts after the camera stops moving.
24
+ *
25
+ * @attribute
26
+ * @title Restart Delay
27
+ */
28
+ restartDelay: number;
29
+ /**
30
+ * Duration in seconds to fade in the rotation speed.
31
+ *
32
+ * @attribute
33
+ * @title Start Fade In Time
34
+ */
35
+ startFadeInTime: number;
36
+ /**
37
+ * Internal timer tracking how long the camera has been idle.
38
+ * @private
39
+ */
40
+ private timer;
41
+ /**
42
+ * Flag to track if rotation has started at least once.
43
+ * @private
44
+ */
45
+ private hasStartedRotating;
46
+ /**
47
+ * Flag to track if we're currently rotating.
48
+ * @private
49
+ */
50
+ private isCurrentlyRotating;
51
+ /**
52
+ * Last known pitch angle for movement detection.
53
+ * @private
54
+ */
55
+ private pitch;
56
+ /**
57
+ * Last known yaw angle for movement detection.
58
+ * @private
59
+ */
60
+ private yaw;
61
+ /**
62
+ * Reference to the camera entity.
63
+ * @private
64
+ */
65
+ private cameraEntity;
66
+ /**
67
+ * Reference to the CameraControls script.
68
+ * @private
69
+ */
70
+ private cameraControls;
71
+ /**
72
+ * Reference to the WalkthroughCamera script (used when CameraControls is absent).
73
+ * @private
74
+ */
75
+ private walkthroughCamera;
76
+ /**
77
+ * Bound event handlers for cleanup.
78
+ * @private
79
+ */
80
+ private onPointerDown?;
81
+ private onKeyDown?;
82
+ /**
83
+ * Handle user input events.
84
+ * @private
85
+ */
86
+ private handleUserInput;
87
+ /**
88
+ * Initialize the script.
89
+ */
90
+ initialize(): void;
91
+ /**
92
+ * Update loop that handles auto-rotation logic.
93
+ * Runs after CameraControls updates.
94
+ */
95
+ postUpdate(dt: number): void;
96
+ /**
97
+ * Smooth step interpolation function.
98
+ *
99
+ * @param {number} x - Input value.
100
+ * @returns {number} - Smoothly interpolated value.
101
+ * @private
102
+ */
103
+ private smoothStep;
104
+ /**
105
+ * Clean up event listeners when the script is destroyed.
106
+ */
107
+ destroy(): void;
108
+ }
109
+ //# sourceMappingURL=AutoRotator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoRotator.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/AutoRotator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAQ,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,qBAAa,WAAY,SAAQ,MAAM;IACrC,MAAM,CAAC,UAAU,SAAiB;IAElC;;;;;OAKG;IACH,KAAK,SAAK;IAEV;;;;;OAKG;IACH,UAAU,SAAK;IAEf;;;;;OAKG;IACH,YAAY,SAAK;IAEjB;;;;;OAKG;IACH,eAAe,SAAK;IAEpB;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAK;IAElB;;;OAGG;IACH,OAAO,CAAC,kBAAkB,CAAS;IAEnC;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAS;IAEpC;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAuB;IAEpC;;;OAGG;IACH,OAAO,CAAC,GAAG,CAAuB;IAElC;;;OAGG;IACH,OAAO,CAAC,YAAY,CAAa;IAEjC;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAa;IAEnC;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAa;IAEtC;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,SAAS,CAAC,CAAa;IAE/B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,UAAU;IAgBV;;;OAGG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM;IAsErB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO;CAQR"}
@@ -0,0 +1,217 @@
1
+ import { Quat, Script, Vec3 } from 'playcanvas';
2
+
3
+ /**
4
+ * Auto-rotator script for PlayCanvas CameraControls.
5
+ * Automatically orbits the camera around its focus point after a period of inactivity.
6
+ */
7
+ export class AutoRotator extends Script {
8
+ static scriptName = 'autoRotator';
9
+
10
+ /**
11
+ * Rotation speed in degrees per second when auto-rotating.
12
+ *
13
+ * @attribute
14
+ * @title Speed
15
+ */
16
+ speed = 4;
17
+
18
+ /**
19
+ * Delay in seconds before auto-rotation starts after initialization.
20
+ *
21
+ * @attribute
22
+ * @title Start Delay
23
+ */
24
+ startDelay = 5;
25
+
26
+ /**
27
+ * Delay in seconds before auto-rotation restarts after the camera stops moving.
28
+ *
29
+ * @attribute
30
+ * @title Restart Delay
31
+ */
32
+ restartDelay = 2;
33
+
34
+ /**
35
+ * Duration in seconds to fade in the rotation speed.
36
+ *
37
+ * @attribute
38
+ * @title Start Fade In Time
39
+ */
40
+ startFadeInTime = 5;
41
+
42
+ /**
43
+ * Internal timer tracking how long the camera has been idle.
44
+ * @private
45
+ */
46
+ timer = 0;
47
+
48
+ /**
49
+ * Flag to track if rotation has started at least once.
50
+ * @private
51
+ */
52
+ hasStartedRotating = false;
53
+
54
+ /**
55
+ * Flag to track if we're currently rotating.
56
+ * @private
57
+ */
58
+ isCurrentlyRotating = false;
59
+
60
+ /**
61
+ * Last known pitch angle for movement detection.
62
+ * @private
63
+ */
64
+ pitch = null;
65
+
66
+ /**
67
+ * Last known yaw angle for movement detection.
68
+ * @private
69
+ */
70
+ yaw = null;
71
+
72
+ /**
73
+ * Reference to the camera entity.
74
+ * @private
75
+ */
76
+ cameraEntity = null;
77
+
78
+ /**
79
+ * Reference to the CameraControls script.
80
+ * @private
81
+ */
82
+ cameraControls = null;
83
+
84
+ /**
85
+ * Reference to the WalkthroughCamera script (used when CameraControls is absent).
86
+ * @private
87
+ */
88
+ walkthroughCamera = null;
89
+
90
+ /**
91
+ * Bound event handlers for cleanup.
92
+ * @private
93
+ */
94
+
95
+ /**
96
+ * Handle user input events.
97
+ * @private
98
+ */
99
+ handleUserInput() {
100
+ this.timer = 0;
101
+ this.isCurrentlyRotating = false;
102
+ this.hasStartedRotating = true;
103
+ }
104
+
105
+ /**
106
+ * Initialize the script.
107
+ */
108
+ initialize() {
109
+ this.onPointerDown = this.handleUserInput.bind(this);
110
+ this.onKeyDown = this.handleUserInput.bind(this);
111
+ if (this.app.graphicsDevice.canvas) {
112
+ this.app.graphicsDevice.canvas.addEventListener('pointerdown', this.onPointerDown);
113
+ }
114
+ window.addEventListener('keydown', this.onKeyDown);
115
+ this.cameraEntity = this.entity.findByName('camera');
116
+ if (this.cameraEntity) {
117
+ this.cameraControls = this.cameraEntity.script?.cameraControls ?? null;
118
+ this.walkthroughCamera = this.cameraEntity.script?.walkthroughCamera ?? null;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Update loop that handles auto-rotation logic.
124
+ * Runs after CameraControls updates.
125
+ */
126
+ postUpdate(dt) {
127
+ const hasControls = this.cameraControls && this.cameraControls._pose;
128
+ const hasWalkthrough = !!this.walkthroughCamera;
129
+ if (!hasControls && !hasWalkthrough) {
130
+ return;
131
+ }
132
+ const currentPitch = hasControls ? this.cameraControls._pose.angles.x : this.walkthroughCamera.currentPitch;
133
+ const currentYaw = hasControls ? this.cameraControls._pose.angles.y : this.walkthroughCamera.currentYaw;
134
+
135
+ // Initialize angles on first frame
136
+ if (this.pitch === null || this.yaw === null) {
137
+ this.pitch = currentPitch;
138
+ this.yaw = currentYaw;
139
+ }
140
+
141
+ // Check for camera movement only after initial rotation has started and while not actively rotating
142
+ if (this.hasStartedRotating && !this.isCurrentlyRotating && this.pitch !== null && this.yaw !== null) {
143
+ const pitchDiff = Math.abs(this.pitch - currentPitch);
144
+ const yawDiff = Math.abs(this.yaw - currentYaw);
145
+ if (pitchDiff > 0.1 || yawDiff > 0.1) {
146
+ this.pitch = currentPitch;
147
+ this.yaw = currentYaw;
148
+ this.timer = 0;
149
+ this.isCurrentlyRotating = false;
150
+ this.hasStartedRotating = true;
151
+ return;
152
+ }
153
+ }
154
+ this.timer += dt;
155
+
156
+ // Determine which delay to use
157
+ const currentDelay = this.hasStartedRotating ? this.restartDelay : this.startDelay;
158
+
159
+ // Start auto-rotation after delay
160
+ if (this.timer >= currentDelay) {
161
+ this.isCurrentlyRotating = true;
162
+ const time = this.timer - currentDelay;
163
+ const fadeIn = this.smoothStep(time / this.startFadeInTime);
164
+ const yawDelta = dt * fadeIn * this.speed;
165
+ if (hasControls) {
166
+ const pose = this.cameraControls._pose;
167
+ const focusPoint = pose.getFocus(new Vec3());
168
+ const offset = new Vec3().sub2(pose.position.clone(), focusPoint);
169
+ const rotationQuat = new Quat().setFromAxisAngle(Vec3.UP, yawDelta);
170
+ const rotatedOffset = new Vec3();
171
+ rotationQuat.transformVector(offset, rotatedOffset);
172
+ const newPos = new Vec3().add2(focusPoint, rotatedOffset);
173
+ pose.look(newPos, focusPoint);
174
+ if (this.cameraControls._controller?.attach) {
175
+ this.cameraControls._controller.attach(pose, false);
176
+ }
177
+ this.cameraEntity.setPosition(pose.position);
178
+ this.cameraEntity.setEulerAngles(pose.angles);
179
+ this.pitch = pose.angles.x;
180
+ this.yaw = pose.angles.y;
181
+ } else {
182
+ this.walkthroughCamera.orbitStep(yawDelta);
183
+ this.pitch = this.walkthroughCamera.currentPitch;
184
+ this.yaw = this.walkthroughCamera.currentYaw;
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Smooth step interpolation function.
191
+ *
192
+ * @param {number} x - Input value.
193
+ * @returns {number} - Smoothly interpolated value.
194
+ * @private
195
+ */
196
+ smoothStep(x) {
197
+ if (x <= 0) {
198
+ return 0;
199
+ }
200
+ if (x >= 1) {
201
+ return 1;
202
+ }
203
+ return Math.sin((x - 0.5) * Math.PI) * 0.5 + 0.5;
204
+ }
205
+
206
+ /**
207
+ * Clean up event listeners when the script is destroyed.
208
+ */
209
+ destroy() {
210
+ if (this.app.graphicsDevice.canvas && this.onPointerDown) {
211
+ this.app.graphicsDevice.canvas.removeEventListener('pointerdown', this.onPointerDown);
212
+ }
213
+ if (this.onKeyDown) {
214
+ window.removeEventListener('keydown', this.onKeyDown);
215
+ }
216
+ }
217
+ }
@@ -0,0 +1,3 @@
1
+ import { type JSX } from 'react';
2
+ export default function BlockingSpinner(): JSX.Element;
3
+ //# sourceMappingURL=BlockingSpinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/BlockingSpinner.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAIxC,MAAM,CAAC,OAAO,UAAU,eAAe,IAAI,GAAG,CAAC,OAAO,CAyBrD"}
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import { CircularProgress, StyledEngineProvider, useTheme } from '@mui/material';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ export default function BlockingSpinner() {
5
+ const theme = useTheme();
6
+ return /*#__PURE__*/_jsx(StyledEngineProvider, {
7
+ injectFirst: true,
8
+ children: /*#__PURE__*/_jsx(CircularProgress, {
9
+ size: "193",
10
+ sx: {
11
+ height: '200px',
12
+ width: '200px',
13
+ position: 'absolute',
14
+ top: 0,
15
+ bottom: 0,
16
+ left: 0,
17
+ right: 0,
18
+ margin: 'auto',
19
+ '& .MuiCircularProgress-svg': {
20
+ color: theme.palette.TwClrIcnBrand,
21
+ height: '200px',
22
+ width: '200px'
23
+ }
24
+ }
25
+ })
26
+ });
27
+ }
@@ -0,0 +1,9 @@
1
+ import { Vec3 } from 'playcanvas';
2
+ export type BoundaryRingProps = {
3
+ center: Vec3;
4
+ radius: number;
5
+ groundPlane: Vec3[];
6
+ };
7
+ declare const BoundaryRing: ({ center, radius, groundPlane }: BoundaryRingProps) => import("react/jsx-runtime").JSX.Element;
8
+ export default BoundaryRing;
9
+ //# sourceMappingURL=BoundaryRing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundaryRing.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/BoundaryRing.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIlC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,IAAI,EAAE,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,iCAAiC,iBAAiB,4CAsBvE,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,33 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Entity } from '@playcanvas/react';
3
+ import { Script } from '@playcanvas/react/components';
4
+ import { useApp } from '@playcanvas/react/hooks';
5
+ import { BoundaryRingScript } from './boundary-ring';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const BoundaryRing = ({
8
+ center,
9
+ radius,
10
+ groundPlane
11
+ }) => {
12
+ const app = useApp();
13
+ useEffect(() => {
14
+ // Set imperatively rather than via reactive Script props. @playcanvas/react wraps Script
15
+ // in memo() whose shallowEquals returns early on the first prop with a .equals() method
16
+ // (Vec3), so any prop after a Vec3 is never compared and would not propagate.
17
+ // @ts-expect-error - scripts are added dynamically to the entity
18
+ const script = app.root.findByName('boundary-ring')?.script?.boundaryRing;
19
+ if (script) {
20
+ script.center = center;
21
+ script.radius = radius;
22
+ script.groundPlane = groundPlane;
23
+ script.rebuild();
24
+ }
25
+ }, [app, center, radius, groundPlane]);
26
+ return /*#__PURE__*/_jsx(Entity, {
27
+ name: "boundary-ring",
28
+ children: /*#__PURE__*/_jsx(Script, {
29
+ script: BoundaryRingScript
30
+ })
31
+ });
32
+ };
33
+ export default BoundaryRing;
@@ -0,0 +1,16 @@
1
+ export interface CameraInfoStrings {
2
+ cameraInfo: string;
3
+ cameraPosition: string;
4
+ cameraFocusPoint: string;
5
+ }
6
+ export interface CameraState {
7
+ position: [number, number, number];
8
+ focus: [number, number, number];
9
+ }
10
+ interface CameraInfoProps {
11
+ strings: CameraInfoStrings;
12
+ getCameraState: () => CameraState | null;
13
+ }
14
+ declare const CameraInfo: ({ strings, getCameraState }: CameraInfoProps) => import("react/jsx-runtime").JSX.Element | null;
15
+ export default CameraInfo;
16
+ //# sourceMappingURL=CameraInfo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CameraInfo.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/CameraInfo.tsx"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAyBD,UAAU,eAAe;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,cAAc,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;CAC1C;AAED,QAAA,MAAM,UAAU,GAAI,6BAA6B,eAAe,mDA8C/D,CAAC;AAEF,eAAe,UAAU,CAAC"}