@terraware/web-components 4.2.26-rc.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/_vendor/react-multi-carousel/index.js +13 -0
  2. package/_vendor/react-multi-carousel/lib/Arrows.js +13 -0
  3. package/_vendor/react-multi-carousel/lib/Carousel.js +19 -0
  4. package/_vendor/react-multi-carousel/lib/CarouselItems.js +14 -0
  5. package/_vendor/react-multi-carousel/lib/Dots.js +16 -0
  6. package/_vendor/react-multi-carousel/lib/index.js +13 -0
  7. package/_vendor/react-multi-carousel/lib/types.js +13 -0
  8. package/_vendor/react-multi-carousel/lib/utils/clones.js +14 -0
  9. package/_vendor/react-multi-carousel/lib/utils/common.js +13 -0
  10. package/_vendor/react-multi-carousel/lib/utils/dots.js +14 -0
  11. package/_vendor/react-multi-carousel/lib/utils/elementWidth.js +12 -0
  12. package/_vendor/react-multi-carousel/lib/utils/index.js +20 -0
  13. package/_vendor/react-multi-carousel/lib/utils/mouseOrTouchMove.js +14 -0
  14. package/_vendor/react-multi-carousel/lib/utils/next.js +13 -0
  15. package/_vendor/react-multi-carousel/lib/utils/previous.js +14 -0
  16. package/_vendor/react-multi-carousel/lib/utils/throttle.js +12 -0
  17. package/_vendor/react-multi-carousel/lib/utils/throwError.js +14 -0
  18. package/_virtual/Arrows.js +3 -0
  19. package/_virtual/Carousel.js +3 -0
  20. package/_virtual/CarouselItems.js +3 -0
  21. package/_virtual/Dots.js +3 -0
  22. package/_virtual/_commonjsHelpers.js +5 -0
  23. package/_virtual/clones.js +3 -0
  24. package/_virtual/common.js +3 -0
  25. package/_virtual/dots2.js +3 -0
  26. package/_virtual/elementWidth.js +3 -0
  27. package/_virtual/index.js +7 -0
  28. package/_virtual/index2.js +3 -0
  29. package/_virtual/index3.js +3 -0
  30. package/_virtual/mouseOrTouchMove.js +3 -0
  31. package/_virtual/next.js +3 -0
  32. package/_virtual/previous.js +3 -0
  33. package/_virtual/throttle.js +3 -0
  34. package/_virtual/throwError.js +3 -0
  35. package/_virtual/types.js +3 -0
  36. package/components/AntSwitch/index.js +6 -4
  37. package/components/Autocomplete/Autocomplete.js +19 -16
  38. package/components/Badge/index.js +8 -6
  39. package/components/BusySpinner/index.js +11 -8
  40. package/components/Button/Button.js +12 -9
  41. package/components/Checkbox.js +11 -8
  42. package/components/Confirm/index.js +14 -17
  43. package/components/DatePicker/DatePicker.js +19 -23
  44. package/components/DialogBox/DialogBox.js +25 -20
  45. package/components/Divisor.js +11 -8
  46. package/components/Dropdown.js +18 -15
  47. package/components/EditableTable/index.js +17 -14
  48. package/components/ErrorBox/ErrorBox.js +18 -15
  49. package/components/FileChooser/index.js +20 -15
  50. package/components/FormBottomBar/index.js +15 -12
  51. package/components/Icon/Icon.js +9 -6
  52. package/components/Icon/icons/index.js +252 -251
  53. package/components/IconTooltip/index.js +14 -9
  54. package/components/Map/MapBox.js +35 -32
  55. package/components/Map/MapContainer.js +10 -6
  56. package/components/Map/MapDateSliderControl.js +14 -12
  57. package/components/Map/MapDrawer.js +16 -12
  58. package/components/Map/MapLegend.js +32 -28
  59. package/components/Map/MapViewStyleControl.js +11 -9
  60. package/components/Map/ReactMapboxWrapper.js +1 -1
  61. package/components/Map/index.js +13 -11
  62. package/components/Map/types.js +5 -3
  63. package/components/Map/useMaintainLayerOrder.js +5 -2
  64. package/components/Markdown/index.js +6 -4
  65. package/components/Message/Message.js +25 -20
  66. package/components/MultiSelect/index.js +26 -23
  67. package/components/Navbar/NavFooter.js +8 -5
  68. package/components/Navbar/NavItem.js +14 -11
  69. package/components/Navbar/NavSection.js +10 -7
  70. package/components/Navbar/Navbar.js +16 -11
  71. package/components/Navbar/SubNavbar.js +8 -5
  72. package/components/Note.js +10 -7
  73. package/components/OverlayModal/OverlayModal.js +13 -11
  74. package/components/PageForm/index.js +15 -12
  75. package/components/PhotoChooser/index.js +30 -25
  76. package/components/PhotosCarousel/index.js +15 -18
  77. package/components/Pill/index.js +14 -11
  78. package/components/PillList/index.js +10 -7
  79. package/components/PlacementWrapper/index.js +8 -6
  80. package/components/PopoverMenu/Popover.js +12 -9
  81. package/components/PopoverMenu/index.js +14 -11
  82. package/components/PopoverMultiSelect/index.js +14 -11
  83. package/components/ProgressCircle/ProgressCircle.js +12 -9
  84. package/components/RadioButton.js +9 -6
  85. package/components/Select/Select.js +9 -6
  86. package/components/Select/SelectT.js +30 -26
  87. package/components/Separator/index.js +7 -5
  88. package/components/Size.js +1 -1
  89. package/components/Slider/index.js +9 -6
  90. package/components/SummaryBox.js +13 -10
  91. package/components/Tabs/index.js +22 -18
  92. package/components/TextTruncated/index.js +13 -20
  93. package/components/Textfield/Textfield.js +34 -28
  94. package/components/Textfield/TruncatedTextArea.js +12 -10
  95. package/components/TimelineSlider/TimelineMarker.js +8 -6
  96. package/components/TimelineSlider/TimelineRail.js +6 -4
  97. package/components/TimelineSlider/index.js +14 -12
  98. package/components/Tooltip/Tooltip.js +12 -7
  99. package/components/ViewPhotosDialog/index.js +14 -11
  100. package/components/VirtualWalkthrough/Annotation.js +10 -8
  101. package/components/VirtualWalkthrough/AnnotationEditPane.js +23 -21
  102. package/components/VirtualWalkthrough/AnnotationPanel.js +16 -14
  103. package/components/VirtualWalkthrough/Application.js +9 -7
  104. package/components/VirtualWalkthrough/AutoRotator.js +5 -3
  105. package/components/VirtualWalkthrough/BlockingSpinner.js +10 -7
  106. package/components/VirtualWalkthrough/BoundaryRing.js +8 -6
  107. package/components/VirtualWalkthrough/BoundaryWall.js +8 -6
  108. package/components/VirtualWalkthrough/CameraInfo.js +15 -13
  109. package/components/VirtualWalkthrough/ControlsInfoPane.js +59 -57
  110. package/components/VirtualWalkthrough/GradientSky.js +8 -6
  111. package/components/VirtualWalkthrough/SplatControls.js +37 -35
  112. package/components/VirtualWalkthrough/SplatCrop.js +6 -4
  113. package/components/VirtualWalkthrough/SplatFadeCrop.js +7 -5
  114. package/components/VirtualWalkthrough/SplatModel.js +17 -14
  115. package/components/VirtualWalkthrough/SplatRevealRain.js +6 -4
  116. package/components/VirtualWalkthrough/TfAnnotationManager.js +8 -5
  117. package/components/VirtualWalkthrough/TfXrNavigation.js +7 -5
  118. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +47 -45
  119. package/components/VirtualWalkthrough/VrAnnotationPanel.js +9 -7
  120. package/components/VirtualWalkthrough/XrAnnotationInteraction.js +9 -7
  121. package/components/VirtualWalkthrough/XrExitButton.js +9 -7
  122. package/components/VirtualWalkthrough/XrGazeDwell.js +9 -7
  123. package/components/VirtualWalkthrough/XrPointerRay.js +9 -7
  124. package/components/VirtualWalkthrough/boundary-ring.js +7 -5
  125. package/components/VirtualWalkthrough/boundary-wall.js +8 -6
  126. package/components/VirtualWalkthrough/groundPlane.js +6 -3
  127. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +5 -2
  128. package/components/VirtualWalkthrough/splatFormat.js +6 -4
  129. package/components/VirtualWalkthrough/vr-annotation-panel-layout.js +4 -2
  130. package/components/VirtualWalkthrough/vr-annotation-panel.js +8 -5
  131. package/components/VirtualWalkthrough/walkthrough-camera.js +6 -4
  132. package/components/VirtualWalkthrough/xr-annotation-candidates.js +8 -6
  133. package/components/VirtualWalkthrough/xr-annotation-interaction.js +9 -6
  134. package/components/VirtualWalkthrough/xr-annotation-targeting.js +5 -2
  135. package/components/VirtualWalkthrough/xr-button-arming.js +4 -2
  136. package/components/VirtualWalkthrough/xr-button-hold.js +5 -3
  137. package/components/VirtualWalkthrough/xr-exit-button.js +10 -8
  138. package/components/VirtualWalkthrough/xr-face-buttons.js +6 -4
  139. package/components/VirtualWalkthrough/xr-gaze-dwell-state.js +5 -3
  140. package/components/VirtualWalkthrough/xr-gaze-dwell.js +9 -7
  141. package/components/VirtualWalkthrough/xr-interactive-ui.js +10 -8
  142. package/components/VirtualWalkthrough/xr-pointer-ray.js +5 -3
  143. package/components/VirtualWalkthrough/xr-progress-pie.js +4 -2
  144. package/components/VirtualWalkthrough/xr-ray-quad.js +5 -2
  145. package/components/VirtualWalkthrough/xr-scene-bounds.js +5 -3
  146. package/components/VirtualWalkthrough/xr-teleport-gesture.js +4 -2
  147. package/components/svg/BlobbyGrayIconImage.js +13 -11
  148. package/components/svg/BlobbyGrayIconImport.js +13 -11
  149. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +13 -11
  150. package/components/svg/BlobbyIconCloudChecked.js +41 -39
  151. package/components/svg/BlobbyIconExportOrUploadPhoto.js +41 -39
  152. package/components/svg/BlobbyIconFolder.js +41 -39
  153. package/components/svg/BlobbyIconGraphReport.js +41 -39
  154. package/components/svg/BlobbyIconHappy.js +41 -39
  155. package/components/svg/BlobbyIconHeartMonitor.js +41 -39
  156. package/components/svg/BlobbyIconLeaf.js +41 -39
  157. package/components/svg/BlobbyIconLibrary.js +41 -39
  158. package/components/svg/BlobbyIconNursery.js +41 -39
  159. package/components/svg/BlobbyIconOrganization.js +41 -39
  160. package/components/svg/BlobbyIconParchment.js +41 -39
  161. package/components/svg/BlobbyIconPeople.js +41 -39
  162. package/components/svg/BlobbyIconSeedBank.js +41 -39
  163. package/components/svg/BlobbyIconSeedling.js +41 -39
  164. package/components/svg/BlobbyIconSeeds.js +41 -39
  165. package/components/svg/BlobbyIconSite.js +42 -40
  166. package/components/svg/BlobbyIconSparkles.js +41 -39
  167. package/components/svg/BlobbyIconWrench.js +41 -39
  168. package/components/svg/Bug.js +8 -6
  169. package/components/svg/Calendar.js +8 -6
  170. package/components/svg/CaretDown.js +8 -6
  171. package/components/svg/CaretLeft.js +8 -6
  172. package/components/svg/CaretRight.js +8 -6
  173. package/components/svg/CaretUp.js +8 -6
  174. package/components/svg/ChevronDown.js +8 -6
  175. package/components/svg/ChevronUp.js +8 -6
  176. package/components/svg/Close.js +8 -6
  177. package/components/svg/Critical.js +8 -6
  178. package/components/svg/Edit.js +41 -39
  179. package/components/svg/Error.js +8 -6
  180. package/components/svg/Filter.js +8 -6
  181. package/components/svg/Folder.js +8 -6
  182. package/components/svg/Help.js +8 -6
  183. package/components/svg/Home.js +8 -6
  184. package/components/svg/IconAdd.js +8 -6
  185. package/components/svg/IconArrowRight.js +8 -6
  186. package/components/svg/IconBusinessNetwork.js +8 -6
  187. package/components/svg/IconCalendar.js +8 -6
  188. package/components/svg/IconCancel.js +8 -6
  189. package/components/svg/IconChargingBattery.js +8 -6
  190. package/components/svg/IconChecklist.js +8 -6
  191. package/components/svg/IconCheckmark.js +8 -6
  192. package/components/svg/IconCoinInHand.js +8 -6
  193. package/components/svg/IconColumns.js +8 -6
  194. package/components/svg/IconComment.js +8 -6
  195. package/components/svg/IconDashboard.js +8 -6
  196. package/components/svg/IconDataMigration.js +8 -6
  197. package/components/svg/IconDocument.js +8 -6
  198. package/components/svg/IconDownloadFromTheCloud.js +8 -6
  199. package/components/svg/IconEdit.js +8 -6
  200. package/components/svg/IconExpand.js +8 -6
  201. package/components/svg/IconExport.js +8 -6
  202. package/components/svg/IconExternalLink.js +8 -6
  203. package/components/svg/IconEye.js +8 -6
  204. package/components/svg/IconEyeOff.js +8 -6
  205. package/components/svg/IconFile.js +8 -6
  206. package/components/svg/IconFolder.js +8 -6
  207. package/components/svg/IconFullScreen.js +8 -6
  208. package/components/svg/IconFutures.js +8 -6
  209. package/components/svg/IconGraphReport.js +8 -6
  210. package/components/svg/IconHeartMonitor.js +8 -6
  211. package/components/svg/IconHelp.js +8 -6
  212. package/components/svg/IconHistory.js +8 -6
  213. package/components/svg/IconImport.js +8 -6
  214. package/components/svg/IconIndex.js +8 -6
  215. package/components/svg/IconLayers.js +8 -6
  216. package/components/svg/IconLibrary.js +8 -6
  217. package/components/svg/IconList.js +8 -6
  218. package/components/svg/IconLivePlant.js +8 -6
  219. package/components/svg/IconLocations.js +8 -6
  220. package/components/svg/IconMail.js +8 -6
  221. package/components/svg/IconManager.js +8 -6
  222. package/components/svg/IconMarker.js +8 -6
  223. package/components/svg/IconMenu.js +8 -6
  224. package/components/svg/IconMenuHorizontal.js +8 -6
  225. package/components/svg/IconModule.js +8 -6
  226. package/components/svg/IconMyLocation.js +8 -6
  227. package/components/svg/IconNote.js +8 -6
  228. package/components/svg/IconNursery.js +8 -6
  229. package/components/svg/IconOrg.js +8 -6
  230. package/components/svg/IconParchment.js +8 -6
  231. package/components/svg/IconPhoto.js +8 -6
  232. package/components/svg/IconPlantsFilled.js +8 -6
  233. package/components/svg/IconRedo.js +8 -6
  234. package/components/svg/IconRestorationSite.js +8 -6
  235. package/components/svg/IconSeedBank.js +8 -6
  236. package/components/svg/IconSeedling.js +8 -6
  237. package/components/svg/IconSettings.js +8 -6
  238. package/components/svg/IconSlice.js +8 -6
  239. package/components/svg/IconSubmit.js +8 -6
  240. package/components/svg/IconSubtract.js +8 -6
  241. package/components/svg/IconSynced.js +8 -6
  242. package/components/svg/IconTrashCan.js +8 -6
  243. package/components/svg/IconTreasureMap.js +8 -6
  244. package/components/svg/IconUnavailable.js +8 -6
  245. package/components/svg/IconUndo.js +8 -6
  246. package/components/svg/IconVariable.js +8 -6
  247. package/components/svg/IconVideo.js +9 -7
  248. package/components/svg/IconWifi.js +8 -6
  249. package/components/svg/Info.js +8 -6
  250. package/components/svg/Key.js +8 -6
  251. package/components/svg/Leaf.js +8 -6
  252. package/components/svg/Lock.js +8 -6
  253. package/components/svg/Logo.js +16 -14
  254. package/components/svg/MenuVertical.js +8 -6
  255. package/components/svg/Notification.js +8 -6
  256. package/components/svg/Person.js +8 -6
  257. package/components/svg/Plus.js +8 -6
  258. package/components/svg/RestorationSite.js +8 -6
  259. package/components/svg/Search.js +8 -6
  260. package/components/svg/Seeds.js +8 -6
  261. package/components/svg/Site.js +8 -6
  262. package/components/svg/Sparkles.js +8 -6
  263. package/components/svg/Species.js +8 -6
  264. package/components/svg/Species2.js +41 -39
  265. package/components/svg/Spinner.js +16 -14
  266. package/components/svg/Star.js +8 -6
  267. package/components/svg/Success.js +8 -6
  268. package/components/svg/SuccessFilled.js +8 -6
  269. package/components/svg/TerrawareLogoDesktop.js +17 -15
  270. package/components/svg/TerrawareLogoMobile.js +9 -7
  271. package/components/svg/Touchscreen.js +8 -6
  272. package/components/svg/UploadCloud.js +41 -39
  273. package/components/svg/Warning.js +8 -6
  274. package/components/svg/WelcomeClipboard.js +32 -30
  275. package/components/svg/index.js +127 -127
  276. package/components/table/EnhancedTableToolbar.js +18 -15
  277. package/components/table/EnhancedTableToolbarV2.js +8 -6
  278. package/components/table/TableCellRenderer.js +37 -32
  279. package/components/table/TableHeader.js +17 -14
  280. package/components/table/TableHeaderItem.js +18 -15
  281. package/components/table/density.js +5 -3
  282. package/components/table/index.js +40 -37
  283. package/components/table/sort.js +6 -4
  284. package/components/table/types.js +1 -1
  285. package/components/types/index.js +1 -1
  286. package/hooks/useBoolean.js +4 -2
  287. package/hooks/useCameraPosition.js +5 -2
  288. package/hooks/useDevicePerformance.js +6 -3
  289. package/hooks/useXr.js +6 -4
  290. package/index.js +55 -58
  291. package/package.json +6 -2
  292. package/style-dictionary-dist/TerrawareTheme.js +2 -1
  293. package/theme.js +5 -2
  294. package/utils/color.js +5 -2
  295. package/utils/date.js +7 -6
  296. package/utils/index.js +4 -5
  297. package/utils/preventDefaultEvent.js +2 -1
  298. package/utils/text.js +3 -2
  299. package/utils/useDeviceInfo.js +2 -1
  300. package/virtualWalkthrough.js +23 -31
  301. package/components/Button/button.test.js +0 -23
  302. package/components/MultiSelect/MultiSelect.test.js +0 -73
  303. package/components/VirtualWalkthrough/TfXrNavigation.test.js +0 -110
  304. package/components/VirtualWalkthrough/boundary-ring.test.js +0 -109
  305. package/components/VirtualWalkthrough/boundary-wall.test.js +0 -203
  306. package/components/VirtualWalkthrough/groundPlane.test.js +0 -45
  307. package/components/VirtualWalkthrough/splatFormat.test.js +0 -51
  308. package/components/VirtualWalkthrough/vr-annotation-panel-layout.test.js +0 -26
  309. package/components/VirtualWalkthrough/xr-annotation-targeting.test.js +0 -66
  310. package/components/VirtualWalkthrough/xr-button-arming.test.js +0 -35
  311. package/components/VirtualWalkthrough/xr-button-hold.test.js +0 -57
  312. package/components/VirtualWalkthrough/xr-exit-button.test.js +0 -23
  313. package/components/VirtualWalkthrough/xr-face-buttons.test.js +0 -82
  314. package/components/VirtualWalkthrough/xr-gaze-dwell-state.test.js +0 -61
  315. package/components/VirtualWalkthrough/xr-interactive-ui.test.js +0 -165
  316. package/components/VirtualWalkthrough/xr-progress-pie.test.js +0 -79
  317. package/components/VirtualWalkthrough/xr-ray-quad.test.js +0 -37
  318. package/components/VirtualWalkthrough/xr-scene-bounds.test.js +0 -70
  319. package/components/VirtualWalkthrough/xr-teleport-gesture.test.js +0 -90
  320. package/components/table/sort.test.js +0 -35
  321. package/utils/date.test.js +0 -84
  322. package/utils/text.test.js +0 -21
package/utils/index.js CHANGED
@@ -1,5 +1,4 @@
1
- import getDateDisplayValue, { getDate, getTodaysDateFormatted, isInTheFuture } from './date';
2
- import preventDefaultEvent from './preventDefaultEvent';
3
- import isWhitespaces from './text';
4
- import useDeviceInfo from './useDeviceInfo';
5
- export { getDate, getDateDisplayValue, getTodaysDateFormatted, isInTheFuture, isWhitespaces, preventDefaultEvent, useDeviceInfo };
1
+ export { getDate, default as getDateDisplayValue, getTodaysDateFormatted, isInTheFuture } from './date.js';
2
+ export { default as preventDefaultEvent } from './preventDefaultEvent.js';
3
+ export { default as isWhitespaces } from './text.js';
4
+ export { default as useDeviceInfo } from './useDeviceInfo.js';
@@ -1,2 +1,3 @@
1
1
  const preventDefault = event => event.preventDefault();
2
- export default preventDefault;
2
+
3
+ export { preventDefault as default };
package/utils/text.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const isWhitespaces = str => str.match(/^\s+$/);
2
- export const titleCase = str => str.split(' ').map(word => {
2
+ const titleCase = str => str.split(' ').map(word => {
3
3
  if (word !== word.toUpperCase()) {
4
4
  const lowerCaseWord = word.toLowerCase();
5
5
  return lowerCaseWord.replace(lowerCaseWord.charAt(0), lowerCaseWord.charAt(0).toUpperCase());
@@ -7,4 +7,5 @@ export const titleCase = str => str.split(' ').map(word => {
7
7
  return word;
8
8
  }
9
9
  }).join(' ');
10
- export default isWhitespaces;
10
+
11
+ export { isWhitespaces as default, titleCase };
@@ -76,4 +76,5 @@ const useDeviceInfo = ({
76
76
  isLandscape: !isPortrait
77
77
  };
78
78
  };
79
- export default useDeviceInfo;
79
+
80
+ export { useDeviceInfo as default };
@@ -1,31 +1,23 @@
1
- /*
2
- * Public entry point for the PlayCanvas-based virtual walkthrough components.
3
- *
4
- * These are kept out of the main index so that importing the core component
5
- * library does not pull in playcanvas. Import them from
6
- * `@terraware/web-components/virtualWalkthrough`.
7
- */
8
- import Annotation from './components/VirtualWalkthrough/Annotation';
9
- import AnnotationEditPane from './components/VirtualWalkthrough/AnnotationEditPane';
10
- import AnnotationPanel from './components/VirtualWalkthrough/AnnotationPanel';
11
- import Application from './components/VirtualWalkthrough/Application';
12
- import { AutoRotator } from './components/VirtualWalkthrough/AutoRotator';
13
- import BlockingSpinner from './components/VirtualWalkthrough/BlockingSpinner';
14
- import BoundaryRing from './components/VirtualWalkthrough/BoundaryRing';
15
- import CameraInfo from './components/VirtualWalkthrough/CameraInfo';
16
- import ControlsInfoPane from './components/VirtualWalkthrough/ControlsInfoPane';
17
- import GradientSky from './components/VirtualWalkthrough/GradientSky';
18
- import SplatControls from './components/VirtualWalkthrough/SplatControls';
19
- import SplatCrop from './components/VirtualWalkthrough/SplatCrop';
20
- import SplatFadeCrop from './components/VirtualWalkthrough/SplatFadeCrop';
21
- import SplatModel from './components/VirtualWalkthrough/SplatModel';
22
- import SplatRevealRain from './components/VirtualWalkthrough/SplatRevealRain';
23
- import { TfAnnotationManager } from './components/VirtualWalkthrough/TfAnnotationManager';
24
- import { TfXrNavigation } from './components/VirtualWalkthrough/TfXrNavigation';
25
- import VirtualWalkthroughViewer from './components/VirtualWalkthrough/VirtualWalkthroughViewer';
26
- import { BoundaryRingScript, boundaryRingMesh } from './components/VirtualWalkthrough/boundary-ring';
27
- import { computeGroundPlane, yOnPlane } from './components/VirtualWalkthrough/groundPlane';
28
- import { detectSplatFormat, splatLoaderFilename } from './components/VirtualWalkthrough/splatFormat';
29
- import { WalkthroughCamera } from './components/VirtualWalkthrough/walkthrough-camera';
30
- import { useDevicePerformance } from './hooks/useDevicePerformance';
31
- export { Annotation, AnnotationEditPane, AnnotationPanel, Application, AutoRotator, BlockingSpinner, BoundaryRing, boundaryRingMesh, BoundaryRingScript, CameraInfo, computeGroundPlane, ControlsInfoPane, detectSplatFormat, GradientSky, SplatControls, SplatCrop, SplatFadeCrop, splatLoaderFilename, SplatModel, SplatRevealRain, TfAnnotationManager, TfXrNavigation, useDevicePerformance, VirtualWalkthroughViewer, WalkthroughCamera, yOnPlane };
1
+ export { default as Annotation } from './components/VirtualWalkthrough/Annotation.js';
2
+ export { default as AnnotationEditPane } from './components/VirtualWalkthrough/AnnotationEditPane.js';
3
+ export { default as AnnotationPanel } from './components/VirtualWalkthrough/AnnotationPanel.js';
4
+ export { default as Application } from './components/VirtualWalkthrough/Application.js';
5
+ export { AutoRotator } from './components/VirtualWalkthrough/AutoRotator.js';
6
+ export { default as BlockingSpinner } from './components/VirtualWalkthrough/BlockingSpinner.js';
7
+ export { default as BoundaryRing } from './components/VirtualWalkthrough/BoundaryRing.js';
8
+ export { default as CameraInfo } from './components/VirtualWalkthrough/CameraInfo.js';
9
+ export { default as ControlsInfoPane } from './components/VirtualWalkthrough/ControlsInfoPane.js';
10
+ export { default as GradientSky } from './components/VirtualWalkthrough/GradientSky.js';
11
+ export { default as SplatControls } from './components/VirtualWalkthrough/SplatControls.js';
12
+ export { default as SplatCrop } from './components/VirtualWalkthrough/SplatCrop.js';
13
+ export { default as SplatFadeCrop } from './components/VirtualWalkthrough/SplatFadeCrop.js';
14
+ export { default as SplatModel } from './components/VirtualWalkthrough/SplatModel.js';
15
+ export { default as SplatRevealRain } from './components/VirtualWalkthrough/SplatRevealRain.js';
16
+ export { TfAnnotationManager } from './components/VirtualWalkthrough/TfAnnotationManager.js';
17
+ export { TfXrNavigation } from './components/VirtualWalkthrough/TfXrNavigation.js';
18
+ export { default as VirtualWalkthroughViewer } from './components/VirtualWalkthrough/VirtualWalkthroughViewer.js';
19
+ export { BoundaryRingScript, boundaryRingMesh } from './components/VirtualWalkthrough/boundary-ring.js';
20
+ export { computeGroundPlane, yOnPlane } from './components/VirtualWalkthrough/groundPlane.js';
21
+ export { detectSplatFormat, splatLoaderFilename } from './components/VirtualWalkthrough/splatFormat.js';
22
+ export { WalkthroughCamera } from './components/VirtualWalkthrough/walkthrough-camera.js';
23
+ export { useDevicePerformance } from './hooks/useDevicePerformance.js';
@@ -1,23 +0,0 @@
1
- import React from 'react';
2
- import { fireEvent, render, screen } from '@testing-library/react';
3
- import Button from './Button';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- test('calls onClick prop when clicked', () => {
6
- const handleClick = jest.fn();
7
- render(/*#__PURE__*/_jsx(Button, {
8
- onClick: handleClick,
9
- label: "Click me"
10
- }));
11
- fireEvent.click(screen.getByText(/click me/i));
12
- expect(handleClick).toHaveBeenCalledTimes(1);
13
- });
14
- test('should not call onClick prop when button is disabled', () => {
15
- const handleClick = jest.fn();
16
- render(/*#__PURE__*/_jsx(Button, {
17
- onClick: handleClick,
18
- label: "Click me",
19
- disabled: true
20
- }));
21
- fireEvent.click(screen.getByText(/click me/i));
22
- expect(handleClick).toHaveBeenCalledTimes(0);
23
- });
@@ -1,73 +0,0 @@
1
- import React from 'react';
2
- import { fireEvent, render, screen } from '@testing-library/react';
3
- import MultiSelect from '.';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- test('show options when placeholder is clicked', () => {
6
- render(/*#__PURE__*/_jsx(MultiSelect, {
7
- onAdd: () => undefined,
8
- onRemove: () => undefined,
9
- options: new Map([[1, 'foo'], [2, 'bar'], [3, 'baz']]),
10
- valueRenderer: v => v,
11
- selectedOptions: [],
12
- placeHolder: "Select..."
13
- }));
14
-
15
- // we should find the placeholder text
16
- const placeHolder = screen.getByText('Select...');
17
- expect(placeHolder).toBeInTheDocument();
18
-
19
- // we should not find the options yet
20
- expect(screen.queryByText('foo')).not.toBeInTheDocument();
21
- expect(screen.queryByText('bar')).not.toBeInTheDocument();
22
- expect(screen.queryByText('baz')).not.toBeInTheDocument();
23
-
24
- // click the placeholder
25
- fireEvent.click(placeHolder);
26
-
27
- // now the options should be visible
28
- expect(screen.queryByText('foo')).toBeInTheDocument();
29
- expect(screen.queryByText('bar')).toBeInTheDocument();
30
- expect(screen.queryByText('baz')).toBeInTheDocument();
31
- });
32
- test('clicking an option calls the onAdd handler', () => {
33
- const handleAdd = jest.fn();
34
- render(/*#__PURE__*/_jsx(MultiSelect, {
35
- onAdd: handleAdd,
36
- onRemove: () => undefined,
37
- options: new Map([[1, 'foo'], [2, 'bar'], [3, 'baz']]),
38
- valueRenderer: v => v,
39
- selectedOptions: [],
40
- placeHolder: "Select..."
41
- }));
42
-
43
- // click the dropdown chevron
44
- const dropdown = screen.getByLabelText('show-options');
45
- fireEvent.click(dropdown);
46
-
47
- // click one of the options
48
- const option = screen.getByText('bar');
49
- fireEvent.click(option);
50
-
51
- // addHandler should have been called with id 2
52
- expect(handleAdd).toBeCalledWith(2);
53
- });
54
- test('clicking the pill remove button calls the onRemove handler', () => {
55
- const handleRemove = jest.fn();
56
- render(/*#__PURE__*/_jsx(MultiSelect, {
57
- onAdd: () => undefined,
58
- onRemove: handleRemove,
59
- options: new Map([[1, 'foo']]),
60
- valueRenderer: v => v,
61
- selectedOptions: [1]
62
- }));
63
-
64
- // find a pill with the 'foo' text
65
- expect(screen.queryByText('foo')).toBeInTheDocument();
66
-
67
- // click the remove button
68
- const removeButton = screen.getByLabelText('remove');
69
- fireEvent.click(removeButton);
70
-
71
- // handleRemove should have been called with id 1
72
- expect(handleRemove).toBeCalledWith(1);
73
- });
@@ -1,110 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
-
3
- // The real base script is an .mjs file that Jest's default CRA transform config never transforms
4
- // (node_modules is excluded), so importing it directly fails to parse. TfXrNavigation.postUpdate
5
- // never calls into the base class, so a stub with no behaviour is enough to satisfy `extends`.
6
- jest.mock('playcanvas/scripts/esm/xr/xr-navigation.mjs', () => ({
7
- XrNavigation: class {}
8
- }));
9
- import { TfXrNavigation } from './TfXrNavigation';
10
- const BOUNDS_CENTER = new Vec3(2, 0, 3);
11
- const BOUNDS_RADIUS = 5;
12
- const makeNavigation = options => {
13
- const translate = jest.fn();
14
- const navigation = Object.create(TfXrNavigation.prototype);
15
- navigation.boundsCenter = BOUNDS_CENTER.clone();
16
- navigation.boundsRadius = options.boundsRadius;
17
- navigation.clampDistance = 0;
18
- navigation.app = {
19
- xr: {
20
- active: options.xrActive
21
- }
22
- };
23
- navigation.entity = {
24
- translate
25
- };
26
- Object.assign(navigation, {
27
- _cameraEntity: {
28
- getPosition: () => options.head
29
- }
30
- });
31
- return {
32
- navigation,
33
- translate
34
- };
35
- };
36
- describe('TfXrNavigation.postUpdate', () => {
37
- it('does not clamp when there is no active XR session, even with the head far outside the circle', () => {
38
- const {
39
- navigation,
40
- translate
41
- } = makeNavigation({
42
- xrActive: false,
43
- boundsRadius: BOUNDS_RADIUS,
44
- head: new Vec3(1000, 1.5, 1000)
45
- });
46
- navigation.postUpdate();
47
- expect(translate).not.toHaveBeenCalled();
48
- expect(navigation.clampDistance).toBe(0);
49
- });
50
- it('does not clamp when boundsRadius is 0', () => {
51
- const {
52
- navigation,
53
- translate
54
- } = makeNavigation({
55
- xrActive: true,
56
- boundsRadius: 0,
57
- head: new Vec3(1000, 1.5, 1000)
58
- });
59
- navigation.postUpdate();
60
- expect(translate).not.toHaveBeenCalled();
61
- expect(navigation.clampDistance).toBe(0);
62
- });
63
- it('does not clamp when the head is inside the circle', () => {
64
- const {
65
- navigation,
66
- translate
67
- } = makeNavigation({
68
- xrActive: true,
69
- boundsRadius: BOUNDS_RADIUS,
70
- head: new Vec3(3, 1.5, 4)
71
- });
72
- navigation.postUpdate();
73
- expect(translate).not.toHaveBeenCalled();
74
- expect(navigation.clampDistance).toBe(0);
75
- });
76
- it('pulls the rig back and records the overshoot when the head is outside the circle in an active session', () => {
77
- const {
78
- navigation,
79
- translate
80
- } = makeNavigation({
81
- xrActive: true,
82
- boundsRadius: BOUNDS_RADIUS,
83
- head: new Vec3(10, 1.5, 3)
84
- });
85
- navigation.postUpdate();
86
- expect(translate).toHaveBeenCalledTimes(1);
87
- expect(translate).toHaveBeenCalledWith(-3, 0, 0);
88
- expect(navigation.clampDistance).toBe(3);
89
- });
90
- it('does not latch clampDistance across frames', () => {
91
- const {
92
- navigation,
93
- translate
94
- } = makeNavigation({
95
- xrActive: true,
96
- boundsRadius: BOUNDS_RADIUS,
97
- head: new Vec3(10, 1.5, 3)
98
- });
99
- navigation.postUpdate();
100
- expect(navigation.clampDistance).toBe(3);
101
- Object.assign(navigation, {
102
- _cameraEntity: {
103
- getPosition: () => new Vec3(3, 1.5, 4)
104
- }
105
- });
106
- navigation.postUpdate();
107
- expect(translate).toHaveBeenCalledTimes(1);
108
- expect(navigation.clampDistance).toBe(0);
109
- });
110
- });
@@ -1,109 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { boundaryRingMesh } from './boundary-ring';
3
- const FLAT = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 0, 1)];
4
- const toVertices = positions => {
5
- const out = [];
6
- for (let i = 0; i < positions.length; i += 3) {
7
- out.push([positions[i], positions[i + 1], positions[i + 2]]);
8
- }
9
- return out;
10
- };
11
- describe('boundaryRingMesh', () => {
12
- it('produces four vertices and six indices per dash', () => {
13
- const geom = boundaryRingMesh({
14
- center: new Vec3(0, 0, 0),
15
- radius: 5,
16
- width: 0.1,
17
- groundPlane: FLAT,
18
- dashCount: 16
19
- });
20
- expect(geom.positions).toHaveLength(16 * 4 * 3);
21
- expect(geom.indices).toHaveLength(16 * 6);
22
- });
23
- it('places every vertex at the inner or outer radius from center in XZ', () => {
24
- const center = new Vec3(2, 0, -3);
25
- const radius = 4;
26
- const width = 0.2;
27
- const inner = radius - width / 2;
28
- const outer = radius + width / 2;
29
- const geom = boundaryRingMesh({
30
- center,
31
- radius,
32
- width,
33
- groundPlane: FLAT,
34
- dashCount: 32
35
- });
36
- for (const [x,, z] of toVertices(geom.positions)) {
37
- const d = Math.sqrt((x - center.x) ** 2 + (z - center.z) ** 2);
38
- const atInner = Math.abs(d - inner) < 1e-6;
39
- const atOuter = Math.abs(d - outer) < 1e-6;
40
- expect(atInner || atOuter).toBe(true);
41
- }
42
- });
43
- it('lifts every vertex onto a tilted ground plane (y = z)', () => {
44
- const tilted = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 1, 1)];
45
- const geom = boundaryRingMesh({
46
- center: new Vec3(0, 0, 0),
47
- radius: 3,
48
- width: 0.1,
49
- groundPlane: tilted,
50
- dashCount: 8
51
- });
52
- for (const [, y, z] of toVertices(geom.positions)) {
53
- expect(y).toBeCloseTo(z);
54
- }
55
- });
56
- it('references only in-range vertices from the index buffer', () => {
57
- const geom = boundaryRingMesh({
58
- center: new Vec3(0, 0, 0),
59
- radius: 5,
60
- width: 0.1,
61
- groundPlane: FLAT,
62
- dashCount: 8
63
- });
64
- const vertexCount = geom.positions.length / 3;
65
- for (const idx of geom.indices) {
66
- expect(idx).toBeGreaterThanOrEqual(0);
67
- expect(idx).toBeLessThan(vertexCount);
68
- }
69
- });
70
- it('returns empty geometry for a non-positive radius', () => {
71
- const geom = boundaryRingMesh({
72
- center: new Vec3(0, 0, 0),
73
- radius: 0,
74
- width: 0.1,
75
- groundPlane: FLAT
76
- });
77
- expect(geom.positions).toHaveLength(0);
78
- expect(geom.indices).toHaveLength(0);
79
- });
80
- it('returns empty geometry for a non-positive width', () => {
81
- const geom = boundaryRingMesh({
82
- center: new Vec3(0, 0, 0),
83
- radius: 5,
84
- width: 0,
85
- groundPlane: FLAT
86
- });
87
- expect(geom.positions).toHaveLength(0);
88
- });
89
- it('returns empty geometry for a non-positive dashCount', () => {
90
- const geom = boundaryRingMesh({
91
- center: new Vec3(0, 0, 0),
92
- radius: 5,
93
- width: 0.1,
94
- groundPlane: FLAT,
95
- dashCount: 0
96
- });
97
- expect(geom.positions).toHaveLength(0);
98
- });
99
- it('returns empty geometry for an invalid ground plane', () => {
100
- const collinear = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(2, 0, 0)];
101
- const geom = boundaryRingMesh({
102
- center: new Vec3(0, 0, 0),
103
- radius: 5,
104
- width: 0.1,
105
- groundPlane: collinear
106
- });
107
- expect(geom.positions).toHaveLength(0);
108
- });
109
- });
@@ -1,203 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { boundaryWallMesh } from './boundary-wall';
3
- const FLAT = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 0, 1)];
4
- const BASE = {
5
- center: new Vec3(0, 0, 0),
6
- radius: 5,
7
- groundPlane: FLAT,
8
- baseY: 0,
9
- topY: 2.5,
10
- gridSpacing: 0.5
11
- };
12
- const toVertices = positions => {
13
- const out = [];
14
- for (let i = 0; i < positions.length; i += 3) {
15
- out.push([positions[i], positions[i + 1], positions[i + 2]]);
16
- }
17
- return out;
18
- };
19
- describe('boundaryWallMesh', () => {
20
- it('produces four vertices, four UVs and six indices per segment', () => {
21
- const geom = boundaryWallMesh({
22
- ...BASE,
23
- segments: 16
24
- });
25
- expect(geom.positions).toHaveLength(16 * 4 * 3);
26
- expect(geom.uvs).toHaveLength(16 * 4 * 2);
27
- expect(geom.indices).toHaveLength(16 * 6);
28
- });
29
- it('places every vertex at the boundary radius in XZ', () => {
30
- const center = new Vec3(2, 0, -3);
31
- const geom = boundaryWallMesh({
32
- ...BASE,
33
- center,
34
- radius: 4,
35
- segments: 32
36
- });
37
- for (const [x,, z] of toVertices(geom.positions)) {
38
- expect(Math.sqrt((x - center.x) ** 2 + (z - center.z) ** 2)).toBeCloseTo(4);
39
- }
40
- });
41
- it('puts the top ring flat at topY for every column, even over tilted ground', () => {
42
- // y = z, so the bottom sweeps -3..3 while the top has to stay pinned at 4.
43
- const tilted = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 1, 1)];
44
- const geom = boundaryWallMesh({
45
- ...BASE,
46
- groundPlane: tilted,
47
- radius: 3,
48
- topY: 4,
49
- segments: 8
50
- });
51
- const verts = toVertices(geom.positions);
52
- // Per segment the order is: bottom@a0, top@a0, bottom@a1, top@a1.
53
- for (let i = 0; i < verts.length; i += 4) {
54
- expect(verts[i + 1][1]).toBeCloseTo(4);
55
- expect(verts[i + 3][1]).toBeCloseTo(4);
56
- }
57
- });
58
- it('sits the base on a tilted ground plane (y = z)', () => {
59
- const tilted = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 1, 1)];
60
- const geom = boundaryWallMesh({
61
- ...BASE,
62
- groundPlane: tilted,
63
- radius: 3,
64
- topY: 4,
65
- segments: 8
66
- });
67
- const verts = toVertices(geom.positions);
68
- for (let i = 0; i < verts.length; i += 4) {
69
- expect(verts[i][1]).toBeCloseTo(verts[i][2]);
70
- expect(verts[i + 2][1]).toBeCloseTo(verts[i + 2][2]);
71
- }
72
- });
73
- it('falls back to a flat base at baseY when no ground plane is supplied', () => {
74
- const geom = boundaryWallMesh({
75
- ...BASE,
76
- groundPlane: [],
77
- baseY: 1.5,
78
- topY: 3.5,
79
- segments: 8
80
- });
81
- const verts = toVertices(geom.positions);
82
- expect(verts).not.toHaveLength(0);
83
- for (let i = 0; i < verts.length; i += 4) {
84
- expect(verts[i][1]).toBeCloseTo(1.5);
85
- expect(verts[i + 1][1]).toBeCloseTo(3.5);
86
- }
87
- });
88
- it('falls back to a flat base for a degenerate ground plane', () => {
89
- const collinear = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(2, 0, 0)];
90
- const geom = boundaryWallMesh({
91
- ...BASE,
92
- groundPlane: collinear,
93
- baseY: -2,
94
- segments: 8
95
- });
96
- const verts = toVertices(geom.positions);
97
- expect(verts).not.toHaveLength(0);
98
- expect(verts[0][1]).toBeCloseTo(-2);
99
- expect(verts[1][1]).toBeCloseTo(2.5);
100
- });
101
- it('reports whole-number grid cell counts derived from gridSpacing', () => {
102
- // Circumference 2*pi*5 = 31.4159; at 0.5 m spacing that rounds to 63 columns.
103
- // The ground is flat at y = 0, so rows = round((2.5 - 0) / 0.5) = 5.
104
- const geom = boundaryWallMesh({
105
- ...BASE,
106
- radius: 5,
107
- topY: 2.5,
108
- gridSpacing: 0.5,
109
- segments: 8
110
- });
111
- expect(geom.columns).toBe(63);
112
- expect(geom.rows).toBe(5);
113
- });
114
- it('derives rows from the average bottom, not from any single column', () => {
115
- // Plane y = x - 1, sampled on a radius-3 circle at 6 columns (0, 60, 120, 180, 240, 300 deg):
116
- // bottoms are 2, 0.5, -2.5, -4, -2.5, 0.5 -> average -1, which no column matches.
117
- // rows = round((2.5 - -1) / 0.5) = round(7) = 7.
118
- const tilted = [new Vec3(1, 0, 0), new Vec3(2, 1, 0), new Vec3(1, 0, 1)];
119
- const geom = boundaryWallMesh({
120
- ...BASE,
121
- groundPlane: tilted,
122
- radius: 3,
123
- topY: 2.5,
124
- segments: 6
125
- });
126
- const bottoms = toVertices(geom.positions).filter((_, index) => index % 2 === 0).map(([, y]) => y);
127
- expect(bottoms).toHaveLength(12);
128
- for (const y of bottoms) {
129
- expect(Math.abs(y + 1)).toBeGreaterThan(1);
130
- }
131
- expect(geom.rows).toBe(7);
132
- });
133
- it('emits u in cell units that wrap exactly at `columns`', () => {
134
- const geom = boundaryWallMesh({
135
- ...BASE,
136
- segments: 8
137
- });
138
- const us = [];
139
- for (let i = 0; i < geom.uvs.length; i += 2) {
140
- us.push(geom.uvs[i]);
141
- }
142
- expect(us[0]).toBeCloseTo(0);
143
- // Last vertex of the last segment closes the loop at exactly `columns`.
144
- expect(us[us.length - 1]).toBeCloseTo(geom.columns);
145
- });
146
- it('emits v as 0 at the base and `rows` at the top', () => {
147
- const geom = boundaryWallMesh({
148
- ...BASE,
149
- segments: 8
150
- });
151
- for (let i = 0; i < geom.uvs.length; i += 8) {
152
- expect(geom.uvs[i + 1]).toBeCloseTo(0);
153
- expect(geom.uvs[i + 3]).toBeCloseTo(geom.rows);
154
- }
155
- });
156
- it('references only in-range vertices from the index buffer', () => {
157
- const geom = boundaryWallMesh({
158
- ...BASE,
159
- segments: 8
160
- });
161
- const vertexCount = geom.positions.length / 3;
162
- for (const idx of geom.indices) {
163
- expect(idx).toBeGreaterThanOrEqual(0);
164
- expect(idx).toBeLessThan(vertexCount);
165
- }
166
- });
167
- it('returns empty geometry for a non-positive radius', () => {
168
- const geom = boundaryWallMesh({
169
- ...BASE,
170
- radius: 0
171
- });
172
- expect(geom.positions).toHaveLength(0);
173
- expect(geom.indices).toHaveLength(0);
174
- });
175
- it('returns empty geometry for a non-positive segment count', () => {
176
- expect(boundaryWallMesh({
177
- ...BASE,
178
- segments: 0
179
- }).positions).toHaveLength(0);
180
- });
181
- it('returns empty geometry for a non-positive grid spacing', () => {
182
- expect(boundaryWallMesh({
183
- ...BASE,
184
- gridSpacing: 0
185
- }).positions).toHaveLength(0);
186
- });
187
- it('returns empty geometry when topY is level with the base', () => {
188
- expect(boundaryWallMesh({
189
- ...BASE,
190
- topY: 0
191
- }).positions).toHaveLength(0);
192
- });
193
- it('returns empty geometry when topY clears only part of a tilted base', () => {
194
- // y = z on a radius-3 circle reaches 3, so a top at 2 is below the far half of the wall.
195
- const tilted = [new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 1, 1)];
196
- expect(boundaryWallMesh({
197
- ...BASE,
198
- groundPlane: tilted,
199
- radius: 3,
200
- topY: 2
201
- }).positions).toHaveLength(0);
202
- });
203
- });
@@ -1,45 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { computeGroundPlane, yOnPlane } from './groundPlane';
3
- describe('computeGroundPlane', () => {
4
- it('returns an up normal for a flat horizontal plane', () => {
5
- const plane = computeGroundPlane([new Vec3(0, 5, 0), new Vec3(1, 5, 0), new Vec3(0, 5, 1)]);
6
- expect(plane).not.toBeNull();
7
- expect(plane.normal.x).toBeCloseTo(0);
8
- expect(plane.normal.y).toBeCloseTo(1);
9
- expect(plane.normal.z).toBeCloseTo(0);
10
- expect(plane.point.y).toBeCloseTo(5);
11
- });
12
- it('flips a downward-facing normal so normal.y >= 0', () => {
13
- const plane = computeGroundPlane([new Vec3(0, 0, 0), new Vec3(0, 0, 1), new Vec3(1, 0, 0)]);
14
- expect(plane).not.toBeNull();
15
- expect(plane.normal.y).toBeCloseTo(1);
16
- });
17
- it('computes a unit normal for a plane tilted 45deg about X (y = z)', () => {
18
- const plane = computeGroundPlane([new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(0, 1, 1)]);
19
- expect(plane).not.toBeNull();
20
- const n = plane.normal;
21
- expect(Math.sqrt(n.x * n.x + n.y * n.y + n.z * n.z)).toBeCloseTo(1);
22
- expect(n.x).toBeCloseTo(0);
23
- expect(n.y).toBeCloseTo(Math.SQRT1_2);
24
- expect(n.z).toBeCloseTo(-Math.SQRT1_2);
25
- });
26
- it('returns null for fewer than 3 points', () => {
27
- expect(computeGroundPlane([new Vec3(0, 0, 0), new Vec3(1, 0, 0)])).toBeNull();
28
- });
29
- it('returns null for collinear points', () => {
30
- expect(computeGroundPlane([new Vec3(0, 0, 0), new Vec3(1, 0, 0), new Vec3(2, 0, 0)])).toBeNull();
31
- });
32
- });
33
- describe('yOnPlane', () => {
34
- it('returns the constant height on a flat plane', () => {
35
- expect(yOnPlane(3, 7, new Vec3(0, 1, 0), new Vec3(0, 5, 0), -1)).toBeCloseTo(5);
36
- });
37
- it('interpolates height on a plane where y = z', () => {
38
- const n = new Vec3(0, Math.SQRT1_2, -Math.SQRT1_2);
39
- expect(yOnPlane(0, 2, n, new Vec3(0, 0, 0), 0)).toBeCloseTo(2);
40
- expect(yOnPlane(10, -3, n, new Vec3(0, 0, 0), 0)).toBeCloseTo(-3);
41
- });
42
- it('returns the fallback when the normal is (near) horizontal', () => {
43
- expect(yOnPlane(1, 1, new Vec3(1, 0, 0), new Vec3(0, 9, 0), 42)).toBe(42);
44
- });
45
- });