@terraware/web-components 4.2.25 → 4.2.26-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 (323) 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.d.ts.map +1 -1
  77. package/components/PhotosCarousel/index.js +17 -13
  78. package/components/Pill/index.js +14 -11
  79. package/components/PillList/index.js +10 -7
  80. package/components/PlacementWrapper/index.js +8 -6
  81. package/components/PopoverMenu/Popover.js +12 -9
  82. package/components/PopoverMenu/index.js +14 -11
  83. package/components/PopoverMultiSelect/index.js +14 -11
  84. package/components/ProgressCircle/ProgressCircle.js +12 -9
  85. package/components/RadioButton.js +9 -6
  86. package/components/Select/Select.js +9 -6
  87. package/components/Select/SelectT.js +30 -26
  88. package/components/Separator/index.js +7 -5
  89. package/components/Size.js +1 -1
  90. package/components/Slider/index.js +9 -6
  91. package/components/SummaryBox.js +13 -10
  92. package/components/Tabs/index.js +22 -18
  93. package/components/TextTruncated/index.js +13 -20
  94. package/components/Textfield/Textfield.js +34 -28
  95. package/components/Textfield/TruncatedTextArea.js +12 -10
  96. package/components/TimelineSlider/TimelineMarker.js +8 -6
  97. package/components/TimelineSlider/TimelineRail.js +6 -4
  98. package/components/TimelineSlider/index.js +14 -12
  99. package/components/Tooltip/Tooltip.js +12 -7
  100. package/components/ViewPhotosDialog/index.js +14 -11
  101. package/components/VirtualWalkthrough/Annotation.js +10 -8
  102. package/components/VirtualWalkthrough/AnnotationEditPane.js +23 -21
  103. package/components/VirtualWalkthrough/AnnotationPanel.js +16 -14
  104. package/components/VirtualWalkthrough/Application.js +9 -7
  105. package/components/VirtualWalkthrough/AutoRotator.js +5 -3
  106. package/components/VirtualWalkthrough/BlockingSpinner.js +10 -7
  107. package/components/VirtualWalkthrough/BoundaryRing.js +8 -6
  108. package/components/VirtualWalkthrough/BoundaryWall.js +8 -6
  109. package/components/VirtualWalkthrough/CameraInfo.js +15 -13
  110. package/components/VirtualWalkthrough/ControlsInfoPane.js +59 -57
  111. package/components/VirtualWalkthrough/GradientSky.js +8 -6
  112. package/components/VirtualWalkthrough/SplatControls.js +37 -35
  113. package/components/VirtualWalkthrough/SplatCrop.js +6 -4
  114. package/components/VirtualWalkthrough/SplatFadeCrop.js +7 -5
  115. package/components/VirtualWalkthrough/SplatModel.js +17 -14
  116. package/components/VirtualWalkthrough/SplatRevealRain.js +6 -4
  117. package/components/VirtualWalkthrough/TfAnnotationManager.js +8 -5
  118. package/components/VirtualWalkthrough/TfXrNavigation.js +7 -5
  119. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +47 -45
  120. package/components/VirtualWalkthrough/VrAnnotationPanel.js +9 -7
  121. package/components/VirtualWalkthrough/XrAnnotationInteraction.js +9 -7
  122. package/components/VirtualWalkthrough/XrExitButton.js +9 -7
  123. package/components/VirtualWalkthrough/XrGazeDwell.js +9 -7
  124. package/components/VirtualWalkthrough/XrPointerRay.js +9 -7
  125. package/components/VirtualWalkthrough/boundary-ring.js +7 -5
  126. package/components/VirtualWalkthrough/boundary-wall.js +8 -6
  127. package/components/VirtualWalkthrough/groundPlane.js +6 -3
  128. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +5 -2
  129. package/components/VirtualWalkthrough/splatFormat.js +6 -4
  130. package/components/VirtualWalkthrough/vr-annotation-panel-layout.js +4 -2
  131. package/components/VirtualWalkthrough/vr-annotation-panel.js +8 -5
  132. package/components/VirtualWalkthrough/walkthrough-camera.js +6 -4
  133. package/components/VirtualWalkthrough/xr-annotation-candidates.js +8 -6
  134. package/components/VirtualWalkthrough/xr-annotation-interaction.js +9 -6
  135. package/components/VirtualWalkthrough/xr-annotation-targeting.js +5 -2
  136. package/components/VirtualWalkthrough/xr-button-arming.js +4 -2
  137. package/components/VirtualWalkthrough/xr-button-hold.js +5 -3
  138. package/components/VirtualWalkthrough/xr-exit-button.js +10 -8
  139. package/components/VirtualWalkthrough/xr-face-buttons.js +6 -4
  140. package/components/VirtualWalkthrough/xr-gaze-dwell-state.js +5 -3
  141. package/components/VirtualWalkthrough/xr-gaze-dwell.js +9 -7
  142. package/components/VirtualWalkthrough/xr-interactive-ui.js +10 -8
  143. package/components/VirtualWalkthrough/xr-pointer-ray.js +5 -3
  144. package/components/VirtualWalkthrough/xr-progress-pie.js +4 -2
  145. package/components/VirtualWalkthrough/xr-ray-quad.js +5 -2
  146. package/components/VirtualWalkthrough/xr-scene-bounds.js +5 -3
  147. package/components/VirtualWalkthrough/xr-teleport-gesture.js +4 -2
  148. package/components/svg/BlobbyGrayIconImage.js +13 -11
  149. package/components/svg/BlobbyGrayIconImport.js +13 -11
  150. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +13 -11
  151. package/components/svg/BlobbyIconCloudChecked.js +41 -39
  152. package/components/svg/BlobbyIconExportOrUploadPhoto.js +41 -39
  153. package/components/svg/BlobbyIconFolder.js +41 -39
  154. package/components/svg/BlobbyIconGraphReport.js +41 -39
  155. package/components/svg/BlobbyIconHappy.js +41 -39
  156. package/components/svg/BlobbyIconHeartMonitor.js +41 -39
  157. package/components/svg/BlobbyIconLeaf.js +41 -39
  158. package/components/svg/BlobbyIconLibrary.js +41 -39
  159. package/components/svg/BlobbyIconNursery.js +41 -39
  160. package/components/svg/BlobbyIconOrganization.js +41 -39
  161. package/components/svg/BlobbyIconParchment.js +41 -39
  162. package/components/svg/BlobbyIconPeople.js +41 -39
  163. package/components/svg/BlobbyIconSeedBank.js +41 -39
  164. package/components/svg/BlobbyIconSeedling.js +41 -39
  165. package/components/svg/BlobbyIconSeeds.js +41 -39
  166. package/components/svg/BlobbyIconSite.js +42 -40
  167. package/components/svg/BlobbyIconSparkles.js +41 -39
  168. package/components/svg/BlobbyIconWrench.js +41 -39
  169. package/components/svg/Bug.js +8 -6
  170. package/components/svg/Calendar.js +8 -6
  171. package/components/svg/CaretDown.js +8 -6
  172. package/components/svg/CaretLeft.js +8 -6
  173. package/components/svg/CaretRight.js +8 -6
  174. package/components/svg/CaretUp.js +8 -6
  175. package/components/svg/ChevronDown.js +8 -6
  176. package/components/svg/ChevronUp.js +8 -6
  177. package/components/svg/Close.js +8 -6
  178. package/components/svg/Critical.js +8 -6
  179. package/components/svg/Edit.js +41 -39
  180. package/components/svg/Error.js +8 -6
  181. package/components/svg/Filter.js +8 -6
  182. package/components/svg/Folder.js +8 -6
  183. package/components/svg/Help.js +8 -6
  184. package/components/svg/Home.js +8 -6
  185. package/components/svg/IconAdd.js +8 -6
  186. package/components/svg/IconArrowRight.js +8 -6
  187. package/components/svg/IconBusinessNetwork.js +8 -6
  188. package/components/svg/IconCalendar.js +8 -6
  189. package/components/svg/IconCancel.js +8 -6
  190. package/components/svg/IconChargingBattery.js +8 -6
  191. package/components/svg/IconChecklist.js +8 -6
  192. package/components/svg/IconCheckmark.js +8 -6
  193. package/components/svg/IconCoinInHand.js +8 -6
  194. package/components/svg/IconColumns.js +8 -6
  195. package/components/svg/IconComment.js +8 -6
  196. package/components/svg/IconDashboard.js +8 -6
  197. package/components/svg/IconDataMigration.js +8 -6
  198. package/components/svg/IconDocument.js +8 -6
  199. package/components/svg/IconDownloadFromTheCloud.js +8 -6
  200. package/components/svg/IconEdit.js +8 -6
  201. package/components/svg/IconExpand.js +8 -6
  202. package/components/svg/IconExport.js +8 -6
  203. package/components/svg/IconExternalLink.js +8 -6
  204. package/components/svg/IconEye.js +8 -6
  205. package/components/svg/IconEyeOff.js +8 -6
  206. package/components/svg/IconFile.js +8 -6
  207. package/components/svg/IconFolder.js +8 -6
  208. package/components/svg/IconFullScreen.js +8 -6
  209. package/components/svg/IconFutures.js +8 -6
  210. package/components/svg/IconGraphReport.js +8 -6
  211. package/components/svg/IconHeartMonitor.js +8 -6
  212. package/components/svg/IconHelp.js +8 -6
  213. package/components/svg/IconHistory.js +8 -6
  214. package/components/svg/IconImport.js +8 -6
  215. package/components/svg/IconIndex.js +8 -6
  216. package/components/svg/IconLayers.js +8 -6
  217. package/components/svg/IconLibrary.js +8 -6
  218. package/components/svg/IconList.js +8 -6
  219. package/components/svg/IconLivePlant.js +8 -6
  220. package/components/svg/IconLocations.js +8 -6
  221. package/components/svg/IconMail.js +8 -6
  222. package/components/svg/IconManager.js +8 -6
  223. package/components/svg/IconMarker.js +8 -6
  224. package/components/svg/IconMenu.js +8 -6
  225. package/components/svg/IconMenuHorizontal.js +8 -6
  226. package/components/svg/IconModule.js +8 -6
  227. package/components/svg/IconMyLocation.js +8 -6
  228. package/components/svg/IconNote.js +8 -6
  229. package/components/svg/IconNursery.js +8 -6
  230. package/components/svg/IconOrg.js +8 -6
  231. package/components/svg/IconParchment.js +8 -6
  232. package/components/svg/IconPhoto.js +8 -6
  233. package/components/svg/IconPlantsFilled.js +8 -6
  234. package/components/svg/IconRedo.js +8 -6
  235. package/components/svg/IconRestorationSite.js +8 -6
  236. package/components/svg/IconSeedBank.js +8 -6
  237. package/components/svg/IconSeedling.js +8 -6
  238. package/components/svg/IconSettings.js +8 -6
  239. package/components/svg/IconSlice.js +8 -6
  240. package/components/svg/IconSubmit.js +8 -6
  241. package/components/svg/IconSubtract.js +8 -6
  242. package/components/svg/IconSynced.js +8 -6
  243. package/components/svg/IconTrashCan.js +8 -6
  244. package/components/svg/IconTreasureMap.js +8 -6
  245. package/components/svg/IconUnavailable.js +8 -6
  246. package/components/svg/IconUndo.js +8 -6
  247. package/components/svg/IconVariable.js +8 -6
  248. package/components/svg/IconVideo.js +9 -7
  249. package/components/svg/IconWifi.js +8 -6
  250. package/components/svg/Info.js +8 -6
  251. package/components/svg/Key.js +8 -6
  252. package/components/svg/Leaf.js +8 -6
  253. package/components/svg/Lock.js +8 -6
  254. package/components/svg/Logo.js +16 -14
  255. package/components/svg/MenuVertical.js +8 -6
  256. package/components/svg/Notification.js +8 -6
  257. package/components/svg/Person.js +8 -6
  258. package/components/svg/Plus.js +8 -6
  259. package/components/svg/RestorationSite.js +8 -6
  260. package/components/svg/Search.js +8 -6
  261. package/components/svg/Seeds.js +8 -6
  262. package/components/svg/Site.js +8 -6
  263. package/components/svg/Sparkles.js +8 -6
  264. package/components/svg/Species.js +8 -6
  265. package/components/svg/Species2.js +41 -39
  266. package/components/svg/Spinner.js +16 -14
  267. package/components/svg/Star.js +8 -6
  268. package/components/svg/Success.js +8 -6
  269. package/components/svg/SuccessFilled.js +8 -6
  270. package/components/svg/TerrawareLogoDesktop.js +17 -15
  271. package/components/svg/TerrawareLogoMobile.js +9 -7
  272. package/components/svg/Touchscreen.js +8 -6
  273. package/components/svg/UploadCloud.js +41 -39
  274. package/components/svg/Warning.js +8 -6
  275. package/components/svg/WelcomeClipboard.js +32 -30
  276. package/components/svg/index.js +127 -127
  277. package/components/table/EnhancedTableToolbar.js +18 -15
  278. package/components/table/EnhancedTableToolbarV2.js +8 -6
  279. package/components/table/TableCellRenderer.js +37 -32
  280. package/components/table/TableHeader.js +17 -14
  281. package/components/table/TableHeaderItem.js +18 -15
  282. package/components/table/density.js +5 -3
  283. package/components/table/index.js +40 -37
  284. package/components/table/sort.js +6 -4
  285. package/components/table/types.js +1 -1
  286. package/components/types/index.js +1 -1
  287. package/hooks/useBoolean.js +4 -2
  288. package/hooks/useCameraPosition.js +5 -2
  289. package/hooks/useDevicePerformance.js +6 -3
  290. package/hooks/useXr.js +6 -4
  291. package/index.js +55 -58
  292. package/package.json +6 -2
  293. package/style-dictionary-dist/TerrawareTheme.js +2 -1
  294. package/theme.js +5 -2
  295. package/utils/color.js +5 -2
  296. package/utils/date.js +7 -6
  297. package/utils/index.js +4 -5
  298. package/utils/preventDefaultEvent.js +2 -1
  299. package/utils/text.js +3 -2
  300. package/utils/useDeviceInfo.js +2 -1
  301. package/virtualWalkthrough.js +23 -31
  302. package/components/Button/button.test.js +0 -23
  303. package/components/MultiSelect/MultiSelect.test.js +0 -73
  304. package/components/VirtualWalkthrough/TfXrNavigation.test.js +0 -110
  305. package/components/VirtualWalkthrough/boundary-ring.test.js +0 -109
  306. package/components/VirtualWalkthrough/boundary-wall.test.js +0 -203
  307. package/components/VirtualWalkthrough/groundPlane.test.js +0 -45
  308. package/components/VirtualWalkthrough/splatFormat.test.js +0 -51
  309. package/components/VirtualWalkthrough/vr-annotation-panel-layout.test.js +0 -26
  310. package/components/VirtualWalkthrough/xr-annotation-targeting.test.js +0 -66
  311. package/components/VirtualWalkthrough/xr-button-arming.test.js +0 -35
  312. package/components/VirtualWalkthrough/xr-button-hold.test.js +0 -57
  313. package/components/VirtualWalkthrough/xr-exit-button.test.js +0 -23
  314. package/components/VirtualWalkthrough/xr-face-buttons.test.js +0 -82
  315. package/components/VirtualWalkthrough/xr-gaze-dwell-state.test.js +0 -61
  316. package/components/VirtualWalkthrough/xr-interactive-ui.test.js +0 -165
  317. package/components/VirtualWalkthrough/xr-progress-pie.test.js +0 -79
  318. package/components/VirtualWalkthrough/xr-ray-quad.test.js +0 -37
  319. package/components/VirtualWalkthrough/xr-scene-bounds.test.js +0 -70
  320. package/components/VirtualWalkthrough/xr-teleport-gesture.test.js +0 -90
  321. package/components/table/sort.test.js +0 -35
  322. package/utils/date.test.js +0 -84
  323. package/utils/text.test.js +0 -21
@@ -1,51 +0,0 @@
1
- import { detectSplatFormat, splatLoaderFilename } from './splatFormat';
2
- describe('detectSplatFormat', () => {
3
- it('detects a bundled .sog archive', () => {
4
- expect(detectSplatFormat('https://example.com/scenes/7154.sog')).toBe('sog');
5
- });
6
- it('detects an unbundled sog meta.json', () => {
7
- expect(detectSplatFormat('https://example.com/scenes/7154/meta.json')).toBe('sogUnbundled');
8
- });
9
- it('detects a streamed LOD sog lod-meta.json', () => {
10
- expect(detectSplatFormat('https://example.com/scenes/7154/lod-meta.json')).toBe('sogStreamed');
11
- });
12
- it('detects a .ply model', () => {
13
- expect(detectSplatFormat('https://example.com/scenes/7154.ply')).toBe('ply');
14
- });
15
- it('ignores query strings on signed urls', () => {
16
- expect(detectSplatFormat('https://example.com/7154/meta.json?rlkey=abc123&raw=1')).toBe('sogUnbundled');
17
- });
18
- it('ignores url fragments', () => {
19
- expect(detectSplatFormat('https://example.com/7154/lod-meta.json#frag')).toBe('sogStreamed');
20
- });
21
- it('is case insensitive', () => {
22
- expect(detectSplatFormat('https://example.com/7154/Meta.JSON')).toBe('sogUnbundled');
23
- expect(detectSplatFormat('https://example.com/7154.SOG')).toBe('sog');
24
- });
25
- it('handles a bare filename with no directory', () => {
26
- expect(detectSplatFormat('meta.json')).toBe('sogUnbundled');
27
- });
28
- it('does not mistake lod-meta.json for the unbundled format', () => {
29
- expect(detectSplatFormat('https://example.com/lod-meta.json')).not.toBe('sogUnbundled');
30
- });
31
- it('does not treat an arbitrary .json file as a sog manifest', () => {
32
- expect(detectSplatFormat('https://example.com/scene.json')).toBe('sog');
33
- });
34
- it('falls back to the bundled sog format for extensionless urls', () => {
35
- expect(detectSplatFormat('https://example.com/assets/abc123?raw=1')).toBe('sog');
36
- });
37
- });
38
- describe('splatLoaderFilename', () => {
39
- it('maps the bundled format to a .sog filename so the loader picks the sog bundle parser', () => {
40
- expect(splatLoaderFilename('sog')).toBe('model.sog');
41
- });
42
- it('maps the unbundled format to meta.json so the loader picks the plain sog parser', () => {
43
- expect(splatLoaderFilename('sogUnbundled')).toBe('meta.json');
44
- });
45
- it('maps the streamed format to the exact basename the octree parser matches on', () => {
46
- expect(splatLoaderFilename('sogStreamed')).toBe('lod-meta.json');
47
- });
48
- it('maps ply to a .ply filename', () => {
49
- expect(splatLoaderFilename('ply')).toBe('model.ply');
50
- });
51
- });
@@ -1,26 +0,0 @@
1
- import { wrapText } from './vr-annotation-panel-layout';
2
-
3
- // Each character is 1 unit wide; a space counts as a character within a line.
4
- const measure = s => s.length;
5
- describe('wrapText', () => {
6
- it('returns an empty array for empty or whitespace-only input', () => {
7
- expect(wrapText('', 10, measure)).toEqual([]);
8
- expect(wrapText(' ', 10, measure)).toEqual([]);
9
- });
10
- it('keeps text on one line when it fits', () => {
11
- expect(wrapText('hello world', 11, measure)).toEqual(['hello world']);
12
- });
13
- it('wraps to a new line when the next word would exceed the width', () => {
14
- // 'hello world' is 11 wide; width 10 forces a break before 'world'.
15
- expect(wrapText('hello world', 10, measure)).toEqual(['hello', 'world']);
16
- });
17
- it('packs as many words as fit per line greedily', () => {
18
- expect(wrapText('a bb cc d', 5, measure)).toEqual(['a bb', 'cc d']);
19
- });
20
- it('puts an over-long word on its own line rather than dropping it', () => {
21
- expect(wrapText('tiny enormouslylongword end', 8, measure)).toEqual(['tiny', 'enormouslylongword', 'end']);
22
- });
23
- it('collapses runs of whitespace', () => {
24
- expect(wrapText('a b', 10, measure)).toEqual(['a b']);
25
- });
26
- });
@@ -1,66 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { nearestAnnotationHit } from './xr-annotation-targeting';
3
- describe('nearestAnnotationHit', () => {
4
- const origin = new Vec3(0, 0, 5);
5
- const forward = new Vec3(0, 0, -1);
6
- it('returns null when there are no candidates', () => {
7
- expect(nearestAnnotationHit(origin, forward, [])).toBeNull();
8
- });
9
- it('returns null when the ray misses every candidate', () => {
10
- const candidates = [{
11
- position: new Vec3(0, 5, 0),
12
- radius: 1
13
- }];
14
- expect(nearestAnnotationHit(origin, forward, candidates)).toBeNull();
15
- });
16
- it('returns the index of a single hit candidate', () => {
17
- const candidates = [{
18
- position: new Vec3(0, 0, 0),
19
- radius: 1
20
- }];
21
- expect(nearestAnnotationHit(origin, forward, candidates)).toBe(0);
22
- });
23
- it('returns the nearest candidate when several are hit, regardless of order', () => {
24
- const far = {
25
- position: new Vec3(0, 0, -5),
26
- radius: 1
27
- };
28
- const near = {
29
- position: new Vec3(0, 0, 0),
30
- radius: 1
31
- };
32
- expect(nearestAnnotationHit(origin, forward, [far, near])).toBe(1);
33
- });
34
- it('treats a ray starting inside a sphere as the nearest hit', () => {
35
- const inside = {
36
- position: new Vec3(0, 0, 5),
37
- radius: 1
38
- };
39
- const ahead = {
40
- position: new Vec3(0, 0, 0),
41
- radius: 1
42
- };
43
- expect(nearestAnnotationHit(origin, forward, [ahead, inside])).toBe(1);
44
- });
45
- it('normalizes a non-unit direction', () => {
46
- const candidates = [{
47
- position: new Vec3(0, 0, 0),
48
- radius: 1
49
- }];
50
- expect(nearestAnnotationHit(origin, new Vec3(0, 0, -4), candidates)).toBe(0);
51
- });
52
- it('returns null when the only candidate is behind the ray origin', () => {
53
- const candidates = [{
54
- position: new Vec3(0, 0, 0),
55
- radius: 1
56
- }];
57
- expect(nearestAnnotationHit(origin, new Vec3(0, 0, 1), candidates)).toBeNull();
58
- });
59
- it('registers a tangent graze as a hit', () => {
60
- const candidates = [{
61
- position: new Vec3(0, 0, 0),
62
- radius: 1
63
- }];
64
- expect(nearestAnnotationHit(new Vec3(0, 1, 5), new Vec3(0, 0, -1), candidates)).toBe(0);
65
- });
66
- });
@@ -1,35 +0,0 @@
1
- import { ButtonArmingLatch } from './xr-button-arming';
2
- const source = () => ({});
3
- describe('ButtonArmingLatch', () => {
4
- it('never counts a source pressed from the very first poll, while it stays down', () => {
5
- const latch = new ButtonArmingLatch();
6
- const src = source();
7
- expect(latch.trackPress(src, true)).toBe(false);
8
- expect(latch.trackPress(src, true)).toBe(false);
9
- expect(latch.trackPress(src, true)).toBe(false);
10
- });
11
- it('counts a press that follows a release', () => {
12
- const latch = new ButtonArmingLatch();
13
- const src = source();
14
- latch.trackPress(src, true);
15
- latch.trackPress(src, false);
16
- expect(latch.trackPress(src, true)).toBe(true);
17
- });
18
- it('tracks each input source independently, so one held from the first poll does not block another', () => {
19
- const latch = new ButtonArmingLatch();
20
- const held = source();
21
- const other = source();
22
- latch.trackPress(held, true);
23
- latch.trackPress(other, false);
24
- expect(latch.trackPress(held, true)).toBe(false);
25
- expect(latch.trackPress(other, true)).toBe(true);
26
- });
27
- it('stays armed across later press/release cycles', () => {
28
- const latch = new ButtonArmingLatch();
29
- const src = source();
30
- latch.trackPress(src, false);
31
- expect(latch.trackPress(src, true)).toBe(true);
32
- latch.trackPress(src, false);
33
- expect(latch.trackPress(src, true)).toBe(true);
34
- });
35
- });
@@ -1,57 +0,0 @@
1
- import { INITIAL_HOLD_STATE, advanceHold } from './xr-button-hold';
2
- const THRESHOLD = 1.25;
3
-
4
- /** Arms the timer the way a real release does, so a press can start accumulating. */
5
- const released = () => advanceHold(INITIAL_HOLD_STATE, false, 0.1, THRESHOLD).state;
6
- describe('advanceHold', () => {
7
- it('ignores a button that is already held when tracking starts', () => {
8
- const result = advanceHold(INITIAL_HOLD_STATE, true, 2, THRESHOLD);
9
- expect(result.progress).toBe(0);
10
- expect(result.justFired).toBe(false);
11
- });
12
- it('stays unarmed for as long as a pre-held button is down', () => {
13
- let state = INITIAL_HOLD_STATE;
14
- for (let frame = 0; frame < 5; frame += 1) {
15
- state = advanceHold(state, true, 1, THRESHOLD).state;
16
- }
17
- expect(advanceHold(state, true, 1, THRESHOLD).justFired).toBe(false);
18
- });
19
- it('arms on release so the next press accumulates', () => {
20
- expect(advanceHold(released(), true, 0.5, THRESHOLD).progress).toBeCloseTo(0.4);
21
- });
22
- it('accumulates progress across frames', () => {
23
- let state = released();
24
- let progress = 0;
25
- for (let frame = 0; frame < 3; frame += 1) {
26
- const result = advanceHold(state, true, 0.25, THRESHOLD);
27
- state = result.state;
28
- progress = result.progress;
29
- }
30
- expect(progress).toBeCloseTo(0.6);
31
- });
32
- it('fires once when the hold reaches the threshold', () => {
33
- const partial = advanceHold(released(), true, 1, THRESHOLD).state;
34
- const firing = advanceHold(partial, true, 1, THRESHOLD);
35
- expect(firing.justFired).toBe(true);
36
- expect(firing.progress).toBe(1);
37
- expect(advanceHold(firing.state, true, 1, THRESHOLD).justFired).toBe(false);
38
- });
39
- it('clamps progress to the threshold', () => {
40
- const result = advanceHold(released(), true, 99, THRESHOLD);
41
- expect(result.progress).toBe(1);
42
- expect(result.justFired).toBe(true);
43
- });
44
- it('resets to zero on release', () => {
45
- const partial = advanceHold(released(), true, 1, THRESHOLD).state;
46
- const result = advanceHold(partial, false, 0.1, THRESHOLD);
47
- expect(result.progress).toBe(0);
48
- expect(result.state.elapsed).toBe(0);
49
- });
50
- it('fires again only after a fresh press', () => {
51
- const fired = advanceHold(advanceHold(released(), true, 1, THRESHOLD).state, true, 1, THRESHOLD).state;
52
- const afterRelease = advanceHold(fired, false, 0.1, THRESHOLD).state;
53
- const rePressed = advanceHold(afterRelease, true, 1, THRESHOLD);
54
- expect(rePressed.justFired).toBe(false);
55
- expect(advanceHold(rePressed.state, true, 1, THRESHOLD).justFired).toBe(true);
56
- });
57
- });
@@ -1,23 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { raySphereIntersect } from './xr-exit-button';
3
- describe('raySphereIntersect', () => {
4
- const CENTER = new Vec3(0, 0, 0);
5
- it('hits a sphere straight ahead of the ray', () => {
6
- expect(raySphereIntersect(new Vec3(0, 0, 5), new Vec3(0, 0, -1), CENTER, 1)).toBe(true);
7
- });
8
- it('misses a sphere off to the side', () => {
9
- expect(raySphereIntersect(new Vec3(0, 5, 5), new Vec3(0, 0, -1), CENTER, 1)).toBe(false);
10
- });
11
- it('misses when the sphere is behind the ray origin', () => {
12
- expect(raySphereIntersect(new Vec3(0, 0, 5), new Vec3(0, 0, 1), CENTER, 1)).toBe(false);
13
- });
14
- it('hits when the ray origin is inside the sphere', () => {
15
- expect(raySphereIntersect(new Vec3(0, 0, 0), new Vec3(1, 0, 0), CENTER, 1)).toBe(true);
16
- });
17
- it('normalizes a non-unit direction', () => {
18
- expect(raySphereIntersect(new Vec3(0, 0, 5), new Vec3(0, 0, -3), CENTER, 1)).toBe(true);
19
- });
20
- it('grazes a tangent sphere', () => {
21
- expect(raySphereIntersect(new Vec3(0, 1, 5), new Vec3(0, 0, -1), CENTER, 1)).toBe(true);
22
- });
23
- });
@@ -1,82 +0,0 @@
1
- import { FaceButtonPressTracker, faceButtonPressed, secondaryFaceButtonPressed } from './xr-face-buttons';
2
-
3
- /** Fake input source whose gamepad reports `pressedIndices` as held. */
4
- const source = (pressedIndices, buttonCount = 6) => ({
5
- gamepad: {
6
- buttons: Array.from({
7
- length: buttonCount
8
- }, (_, index) => ({
9
- pressed: pressedIndices.includes(index)
10
- }))
11
- }
12
- });
13
- const handTrackedSource = () => ({});
14
- describe('faceButtonPressed', () => {
15
- it('is false for an input source with no gamepad', () => {
16
- expect(faceButtonPressed(handTrackedSource())).toBe(false);
17
- });
18
- it('is false when the gamepad has fewer buttons than the face buttons', () => {
19
- expect(faceButtonPressed(source([0], 2))).toBe(false);
20
- });
21
- it('is true when A/X is pressed', () => {
22
- expect(faceButtonPressed(source([4]))).toBe(true);
23
- });
24
- it('is true when B/Y is pressed', () => {
25
- expect(faceButtonPressed(source([5]))).toBe(true);
26
- });
27
- it('is false when only the trigger and grip are pressed', () => {
28
- expect(faceButtonPressed(source([0, 1]))).toBe(false);
29
- });
30
- it('is false when nothing is pressed', () => {
31
- expect(faceButtonPressed(source([]))).toBe(false);
32
- });
33
- });
34
- describe('secondaryFaceButtonPressed', () => {
35
- it('is true when B/Y is pressed', () => {
36
- expect(secondaryFaceButtonPressed(source([5]))).toBe(true);
37
- });
38
- it('is false when only A/X is pressed', () => {
39
- expect(secondaryFaceButtonPressed(source([4]))).toBe(false);
40
- });
41
- it('is false for an input source with no gamepad', () => {
42
- expect(secondaryFaceButtonPressed(handTrackedSource())).toBe(false);
43
- });
44
- it('is false when the gamepad has fewer buttons than the face buttons', () => {
45
- expect(secondaryFaceButtonPressed(source([0], 2))).toBe(false);
46
- });
47
- });
48
- describe('FaceButtonPressTracker', () => {
49
- it('fires once for a held press and re-arms after release', () => {
50
- const tracker = new FaceButtonPressTracker();
51
- // One persistent source whose button state mutates, as a real XrInputSource does across frames.
52
- const buttons = Array.from({
53
- length: 6
54
- }, () => ({
55
- pressed: false
56
- }));
57
- const controller = {
58
- gamepad: {
59
- buttons
60
- }
61
- };
62
- const holdFaceButton = pressed => {
63
- buttons[4].pressed = pressed;
64
- };
65
- expect(tracker.justPressed(controller)).toBe(false);
66
- holdFaceButton(true);
67
- expect(tracker.justPressed(controller)).toBe(true);
68
- expect(tracker.justPressed(controller)).toBe(false);
69
- holdFaceButton(false);
70
- expect(tracker.justPressed(controller)).toBe(false);
71
- holdFaceButton(true);
72
- expect(tracker.justPressed(controller)).toBe(true);
73
- });
74
- it('tracks each input source independently', () => {
75
- const tracker = new FaceButtonPressTracker();
76
- const left = source([4]);
77
- const right = source([]);
78
- expect(tracker.justPressed(left)).toBe(true);
79
- expect(tracker.justPressed(right)).toBe(false);
80
- expect(tracker.justPressed(left)).toBe(false);
81
- });
82
- });
@@ -1,61 +0,0 @@
1
- import { INITIAL_DWELL_STATE, advanceDwell } from './xr-gaze-dwell-state';
2
- const THRESHOLD = 1.5;
3
- describe('advanceDwell', () => {
4
- it('stays reset when there is no gaze target', () => {
5
- const r = advanceDwell({
6
- targetIndex: 2,
7
- elapsed: 1.0
8
- }, null, 0.1, THRESHOLD);
9
- expect(r.state).toEqual(INITIAL_DWELL_STATE);
10
- expect(r.progress).toBe(0);
11
- expect(r.justOpened).toBe(false);
12
- });
13
- it('resets to zero when the target changes', () => {
14
- const r = advanceDwell({
15
- targetIndex: 0,
16
- elapsed: 1.0
17
- }, 1, 0.1, THRESHOLD);
18
- expect(r.state).toEqual({
19
- targetIndex: 1,
20
- elapsed: 0
21
- });
22
- expect(r.progress).toBe(0);
23
- expect(r.justOpened).toBe(false);
24
- });
25
- it('accumulates dwell time while the same target is held', () => {
26
- const r = advanceDwell({
27
- targetIndex: 3,
28
- elapsed: 0.5
29
- }, 3, 0.25, THRESHOLD);
30
- expect(r.state).toEqual({
31
- targetIndex: 3,
32
- elapsed: 0.75
33
- });
34
- expect(r.progress).toBeCloseTo(0.5, 5);
35
- expect(r.justOpened).toBe(false);
36
- });
37
- it('fires justOpened once when crossing the threshold and clamps elapsed', () => {
38
- const r = advanceDwell({
39
- targetIndex: 3,
40
- elapsed: 1.4
41
- }, 3, 0.5, THRESHOLD);
42
- expect(r.justOpened).toBe(true);
43
- expect(r.progress).toBe(1);
44
- expect(r.state).toEqual({
45
- targetIndex: 3,
46
- elapsed: THRESHOLD
47
- });
48
- });
49
- it('does not re-fire while the target stays held past the threshold', () => {
50
- const r = advanceDwell({
51
- targetIndex: 3,
52
- elapsed: THRESHOLD
53
- }, 3, 0.5, THRESHOLD);
54
- expect(r.justOpened).toBe(false);
55
- expect(r.progress).toBe(1);
56
- expect(r.state).toEqual({
57
- targetIndex: 3,
58
- elapsed: THRESHOLD
59
- });
60
- });
61
- });
@@ -1,165 +0,0 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { VrAnnotationPanel } from './vr-annotation-panel';
3
- import { XrExitButton } from './xr-exit-button';
4
- import { rayHitsAnnotationHotspot, rayHitsAnnotationPanel, rayHitsExitButton, rayHitsInteractiveUi } from './xr-interactive-ui';
5
-
6
- // Jest cannot parse the PlayCanvas ESM scripts that xr-annotation-candidates imports.
7
- jest.mock('playcanvas/scripts/esm/annotations.mjs', () => ({
8
- Annotation: {
9
- scriptName: 'annotation'
10
- }
11
- }));
12
- const ORIGIN = new Vec3(0, 0, 5);
13
- const FORWARD = new Vec3(0, 0, -1);
14
-
15
- /** Fake annotation hotspot entity: unit quad at `position`, scale 1, with the stock open callback. */
16
- const hotspot = position => ({
17
- getPosition: () => position,
18
- getWorldTransform: () => ({
19
- getScale: out => out.set(1, 1, 1)
20
- }),
21
- script: {
22
- get: () => ({
23
- onVrOpenCallback: () => undefined
24
- })
25
- }
26
- });
27
- /**
28
- * Fake app whose `findByName` serves only the entities the helpers look up. Each script stub returns
29
- * its fake only for the matching `scriptName`, so a lookup by the wrong name misses - the way a real
30
- * `Script#get` would - instead of silently succeeding.
31
- */
32
- const fakeApp = ({
33
- hotspots,
34
- panelHit,
35
- panelHasScript = true,
36
- exitHit
37
- }) => ({
38
- root: {
39
- findByName: name => {
40
- if (name === 'annotations-root') {
41
- return hotspots ? {
42
- children: hotspots
43
- } : null;
44
- }
45
- if (name === 'vr-annotation-panel') {
46
- if (panelHit === undefined) {
47
- return null;
48
- }
49
- return {
50
- script: {
51
- get: scriptName => scriptName === VrAnnotationPanel.scriptName ? panelHasScript ? {
52
- rayHitsPanel: () => panelHit
53
- } : {} : undefined
54
- }
55
- };
56
- }
57
- if (name === 'xr-exit-button') {
58
- return exitHit === undefined ? null : {
59
- script: {
60
- get: scriptName => scriptName === XrExitButton.scriptName ? {
61
- rayHitsButton: () => exitHit
62
- } : undefined
63
- }
64
- };
65
- }
66
- return null;
67
- }
68
- }
69
- });
70
- describe('rayHitsAnnotationHotspot', () => {
71
- it('is true when the ray enters a hotspot sphere', () => {
72
- const app = fakeApp({
73
- hotspots: [hotspot(new Vec3(0, 0, 0))]
74
- });
75
- expect(rayHitsAnnotationHotspot(app, ORIGIN, FORWARD)).toBe(true);
76
- });
77
- it('is false when the ray misses every hotspot', () => {
78
- const app = fakeApp({
79
- hotspots: [hotspot(new Vec3(0, 8, 0))]
80
- });
81
- expect(rayHitsAnnotationHotspot(app, ORIGIN, FORWARD)).toBe(false);
82
- });
83
- it('is false when there is no annotations root', () => {
84
- expect(rayHitsAnnotationHotspot(fakeApp({}), ORIGIN, FORWARD)).toBe(false);
85
- });
86
-
87
- // Pins the derived radius (HOTSPOT_HALF_EXTENT 0.5 * scale 1 * HIT_RADIUS_PAD 2.5 = 1.25) against
88
- // drift: a hotspot at (0,0,0) or (0,8,0) would pass the two tests above for nearly any radius.
89
- it('is true just inside the derived hit radius', () => {
90
- const app = fakeApp({
91
- hotspots: [hotspot(new Vec3(0, 1.2, 0))]
92
- });
93
- expect(rayHitsAnnotationHotspot(app, ORIGIN, FORWARD)).toBe(true);
94
- });
95
- it('is false just outside the derived hit radius', () => {
96
- const app = fakeApp({
97
- hotspots: [hotspot(new Vec3(0, 1.3, 0))]
98
- });
99
- expect(rayHitsAnnotationHotspot(app, ORIGIN, FORWARD)).toBe(false);
100
- });
101
- });
102
- describe('rayHitsAnnotationPanel', () => {
103
- it('delegates to the panel script', () => {
104
- expect(rayHitsAnnotationPanel(fakeApp({
105
- panelHit: true
106
- }), ORIGIN, FORWARD)).toBe(true);
107
- expect(rayHitsAnnotationPanel(fakeApp({
108
- panelHit: false
109
- }), ORIGIN, FORWARD)).toBe(false);
110
- });
111
- it('is false when no panel is mounted', () => {
112
- expect(rayHitsAnnotationPanel(fakeApp({}), ORIGIN, FORWARD)).toBe(false);
113
- });
114
- it('is false when the panel entity has no hit-test method', () => {
115
- const app = fakeApp({
116
- panelHit: true,
117
- panelHasScript: false
118
- });
119
- expect(rayHitsAnnotationPanel(app, ORIGIN, FORWARD)).toBe(false);
120
- });
121
- });
122
- describe('rayHitsExitButton', () => {
123
- it('delegates to the exit button script', () => {
124
- expect(rayHitsExitButton(fakeApp({
125
- exitHit: true
126
- }), ORIGIN, FORWARD)).toBe(true);
127
- expect(rayHitsExitButton(fakeApp({
128
- exitHit: false
129
- }), ORIGIN, FORWARD)).toBe(false);
130
- });
131
- it('is false when no exit button is mounted', () => {
132
- expect(rayHitsExitButton(fakeApp({}), ORIGIN, FORWARD)).toBe(false);
133
- });
134
- });
135
- describe('rayHitsInteractiveUi', () => {
136
- it('is false when the ray hits nothing interactive', () => {
137
- const app = fakeApp({
138
- hotspots: [hotspot(new Vec3(0, 8, 0))],
139
- panelHit: false,
140
- exitHit: false
141
- });
142
- expect(rayHitsInteractiveUi(app, ORIGIN, FORWARD)).toBe(false);
143
- });
144
- it('is true for a hotspot hit', () => {
145
- const app = fakeApp({
146
- hotspots: [hotspot(new Vec3(0, 0, 0))],
147
- panelHit: false,
148
- exitHit: false
149
- });
150
- expect(rayHitsInteractiveUi(app, ORIGIN, FORWARD)).toBe(true);
151
- });
152
- it('is true for a panel hit', () => {
153
- expect(rayHitsInteractiveUi(fakeApp({
154
- panelHit: true
155
- }), ORIGIN, FORWARD)).toBe(true);
156
- });
157
- it('is true for an exit button hit', () => {
158
- expect(rayHitsInteractiveUi(fakeApp({
159
- exitHit: true
160
- }), ORIGIN, FORWARD)).toBe(true);
161
- });
162
- it('is false in an empty scene', () => {
163
- expect(rayHitsInteractiveUi(fakeApp({}), ORIGIN, FORWARD)).toBe(false);
164
- });
165
- });
@@ -1,79 +0,0 @@
1
- import { drawProgressPie } from './xr-progress-pie';
2
- const TRACK_FILL = 'rgba(255, 255, 255, 0.18)';
3
- const WEDGE_FILL = 'rgba(64, 200, 255, 0.85)';
4
-
5
- /** Minimal 2D-context stand-in that records the arcs drawn and the fill colour used for each. */
6
- const stubContext = () => {
7
- const arcs = [];
8
- const fills = [];
9
- const ctx = {
10
- fillStyle: '',
11
- save: () => undefined,
12
- restore: () => undefined,
13
- beginPath: () => undefined,
14
- moveTo: () => undefined,
15
- closePath: () => undefined,
16
- arc: (_x, _y, radius, start, end) => {
17
- arcs.push({
18
- radius,
19
- start,
20
- end
21
- });
22
- },
23
- fill: () => {
24
- fills.push(ctx.fillStyle);
25
- }
26
- };
27
- return {
28
- ctx: ctx,
29
- arcs,
30
- fills
31
- };
32
- };
33
- describe('drawProgressPie', () => {
34
- it('draws only the full-circle track at zero progress', () => {
35
- const {
36
- ctx,
37
- arcs,
38
- fills
39
- } = stubContext();
40
- drawProgressPie(ctx, 128, 0);
41
- expect(arcs).toHaveLength(1);
42
- expect(arcs[0].end - arcs[0].start).toBeCloseTo(Math.PI * 2);
43
- expect(fills).toEqual([TRACK_FILL]);
44
- });
45
- it('sweeps a quarter turn clockwise from the top at quarter progress', () => {
46
- const {
47
- ctx,
48
- arcs
49
- } = stubContext();
50
- drawProgressPie(ctx, 128, 0.25);
51
- expect(arcs).toHaveLength(2);
52
- expect(arcs[1].start).toBeCloseTo(-Math.PI / 2);
53
- expect(arcs[1].end).toBeCloseTo(0);
54
- });
55
- it('sweeps a full turn at full progress', () => {
56
- const {
57
- ctx,
58
- arcs
59
- } = stubContext();
60
- drawProgressPie(ctx, 128, 1);
61
- expect(arcs[1].end - arcs[1].start).toBeCloseTo(Math.PI * 2);
62
- });
63
- it('fills the wedge over the track', () => {
64
- const {
65
- ctx,
66
- fills
67
- } = stubContext();
68
- drawProgressPie(ctx, 128, 0.5);
69
- expect(fills).toEqual([TRACK_FILL, WEDGE_FILL]);
70
- });
71
- it('scales the radius to the drawn size', () => {
72
- const {
73
- ctx,
74
- arcs
75
- } = stubContext();
76
- drawProgressPie(ctx, 256, 0);
77
- expect(arcs[0].radius).toBeCloseTo(128 * 0.92);
78
- });
79
- });