@nvidia-elements/core 2.9.0 → 2.11.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 (265) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +3 -7
  3. package/dist/accordion/accordion.d.ts +4 -4
  4. package/dist/accordion/accordion2.js +4 -4
  5. package/dist/alert/alert-group.d.ts +1 -1
  6. package/dist/alert/alert-group2.js +1 -1
  7. package/dist/alert/alert.d.ts +1 -1
  8. package/dist/alert/alert2.js +1 -1
  9. package/dist/avatar/avatar-group.d.ts +1 -1
  10. package/dist/avatar/avatar-group2.js +1 -1
  11. package/dist/avatar/avatar.d.ts +1 -1
  12. package/dist/avatar/avatar2.js +1 -1
  13. package/dist/badge/badge.d.ts +1 -1
  14. package/dist/badge/badge2.js +1 -1
  15. package/dist/breadcrumb/breadcrumb.d.ts +2 -1
  16. package/dist/breadcrumb/breadcrumb2.js +1 -1
  17. package/dist/breadcrumb/breadcrumb2.js.map +1 -1
  18. package/dist/bundles/index.d.ts +183 -44
  19. package/dist/bundles/index.js +6 -6
  20. package/dist/button/button.d.ts +1 -1
  21. package/dist/button/button2.js +1 -1
  22. package/dist/button-group/button-group.d.ts +1 -1
  23. package/dist/button-group/button-group2.js +1 -1
  24. package/dist/card/card.d.ts +4 -4
  25. package/dist/card/card2.js +4 -4
  26. package/dist/chat-message/chat-message.d.ts +1 -1
  27. package/dist/chat-message/chat-message2.js +1 -1
  28. package/dist/checkbox/checkbox-group2.js +1 -1
  29. package/dist/checkbox/checkbox2.js +1 -1
  30. package/dist/color/color.d.ts +1 -1
  31. package/dist/color/color2.js +1 -1
  32. package/dist/combobox/combobox.d.ts +2 -2
  33. package/dist/combobox/combobox2.js +1 -1
  34. package/dist/copy-button/copy-button.d.ts +1 -1
  35. package/dist/copy-button/copy-button2.js +1 -1
  36. package/dist/custom-elements-jsx.d.ts +117 -25
  37. package/dist/custom-elements-vue.d.ts +115 -25
  38. package/dist/custom-elements.json +1075 -916
  39. package/dist/data.html.json +55 -7
  40. package/dist/data.snippets.json +45 -45
  41. package/dist/date/date.d.ts +1 -1
  42. package/dist/date/date2.js +1 -1
  43. package/dist/datetime/datetime.d.ts +1 -1
  44. package/dist/datetime/datetime2.js +1 -1
  45. package/dist/dialog/dialog-footer.d.ts +1 -1
  46. package/dist/dialog/dialog-footer2.js +1 -1
  47. package/dist/dialog/dialog-header.d.ts +1 -1
  48. package/dist/dialog/dialog-header2.js +1 -1
  49. package/dist/dialog/dialog.d.ts +1 -1
  50. package/dist/dialog/dialog2.js +1 -1
  51. package/dist/divider/divider.d.ts +1 -1
  52. package/dist/divider/divider2.js +1 -1
  53. package/dist/dot/dot.d.ts +1 -1
  54. package/dist/dot/dot2.js +1 -1
  55. package/dist/drawer/drawer-content.d.ts +1 -1
  56. package/dist/drawer/drawer-content2.js +1 -1
  57. package/dist/drawer/drawer-footer.d.ts +1 -1
  58. package/dist/drawer/drawer-footer2.js +1 -1
  59. package/dist/drawer/drawer-header.d.ts +1 -1
  60. package/dist/drawer/drawer-header2.js +1 -1
  61. package/dist/drawer/drawer.d.ts +1 -1
  62. package/dist/drawer/drawer2.js +1 -1
  63. package/dist/dropdown/dropdown-footer.d.ts +1 -1
  64. package/dist/dropdown/dropdown-footer2.js +1 -1
  65. package/dist/dropdown/dropdown-header.d.ts +1 -1
  66. package/dist/dropdown/dropdown-header2.js +1 -1
  67. package/dist/dropdown/dropdown.d.ts +1 -1
  68. package/dist/dropdown/dropdown2.js +1 -1
  69. package/dist/dropdown-group/dropdown-group.d.ts +1 -1
  70. package/dist/dropdown-group/dropdown-group.js +1 -1
  71. package/dist/dropzone/dropzone.d.ts +1 -1
  72. package/dist/dropzone/dropzone2.js +1 -1
  73. package/dist/file/file2.js +1 -1
  74. package/dist/format-bytes/format-bytes.d.ts +1 -1
  75. package/dist/format-bytes/format-bytes2.js +1 -1
  76. package/dist/format-datetime/format-datetime.d.ts +1 -1
  77. package/dist/format-datetime/format-datetime2.js +1 -1
  78. package/dist/format-number/format-number.d.ts +1 -1
  79. package/dist/format-number/format-number2.js +1 -1
  80. package/dist/format-relative-time/format-relative-time.d.ts +1 -1
  81. package/dist/format-relative-time/format-relative-time2.js +1 -1
  82. package/dist/format-truncate/format-truncate2.js +1 -1
  83. package/dist/forms/control/control2.js +1 -1
  84. package/dist/forms/control-group/control-group.d.ts +3 -1
  85. package/dist/forms/control-group/control-group2.js +1 -1
  86. package/dist/forms/control-group/control-group2.js.map +1 -1
  87. package/dist/forms/control-message/control-message.d.ts +1 -1
  88. package/dist/forms/control-message/control-message2.js +1 -1
  89. package/dist/gauge/gauge.d.ts +1 -1
  90. package/dist/gauge/gauge2.js +1 -1
  91. package/dist/grid/cell/cell.d.ts +1 -1
  92. package/dist/grid/cell/cell2.js +1 -1
  93. package/dist/grid/column/column.d.ts +1 -1
  94. package/dist/grid/column/column2.js +1 -1
  95. package/dist/grid/footer/footer.d.ts +1 -1
  96. package/dist/grid/footer/footer2.js +1 -1
  97. package/dist/grid/grid.d.ts +3 -1
  98. package/dist/grid/grid2.js +1 -1
  99. package/dist/grid/grid2.js.map +1 -1
  100. package/dist/grid/header/header.d.ts +1 -1
  101. package/dist/grid/header/header2.js +1 -1
  102. package/dist/grid/placeholder/placeholder.d.ts +1 -1
  103. package/dist/grid/placeholder/placeholder2.js +1 -1
  104. package/dist/grid/row/row.d.ts +1 -1
  105. package/dist/grid/row/row2.js +1 -1
  106. package/dist/icon/icon.d.ts +1 -1
  107. package/dist/icon/icon2.js +2 -2
  108. package/dist/icon-button/icon-button.d.ts +1 -1
  109. package/dist/icon-button/icon-button2.js +1 -1
  110. package/dist/index.js +1 -1
  111. package/dist/input/input-group2.js +1 -1
  112. package/dist/input/input2.js +1 -1
  113. package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
  114. package/dist/internal/services/global.service.js +1 -1
  115. package/dist/internal/types/index.d.ts +6 -2
  116. package/dist/internal/types/index.js.map +1 -1
  117. package/dist/internal/utils/audit.js +1 -1
  118. package/dist/internal/utils/audit.js.map +1 -1
  119. package/dist/internal/utils/dom.d.ts +3 -1
  120. package/dist/internal/utils/dom.js.map +1 -1
  121. package/dist/logo/logo.d.ts +1 -1
  122. package/dist/logo/logo2.js +1 -1
  123. package/dist/menu/define.d.ts +2 -1
  124. package/dist/menu/define.js +3 -2
  125. package/dist/menu/define.js.map +1 -1
  126. package/dist/menu/index.d.ts +1 -0
  127. package/dist/menu/index.js +3 -2
  128. package/dist/menu/menu-group.d.ts +50 -0
  129. package/dist/menu/menu-group.js +6 -0
  130. package/dist/menu/menu-group.js.map +1 -0
  131. package/dist/menu/menu-group2.js +53 -0
  132. package/dist/menu/menu-group2.js.map +1 -0
  133. package/dist/menu/menu-item.d.ts +2 -1
  134. package/dist/menu/menu-item.js +1 -1
  135. package/dist/menu/menu-item.js.map +1 -1
  136. package/dist/menu/menu-item2.js +2 -2
  137. package/dist/menu/menu-item2.js.map +1 -1
  138. package/dist/menu/menu.d.ts +7 -2
  139. package/dist/menu/menu.examples.js.map +1 -1
  140. package/dist/menu/menu.examples.json +53 -13
  141. package/dist/menu/menu.global.js +1 -1
  142. package/dist/menu/menu.global.js.map +1 -1
  143. package/dist/menu/menu2.js +16 -8
  144. package/dist/menu/menu2.js.map +1 -1
  145. package/dist/month/month.d.ts +1 -1
  146. package/dist/month/month2.js +1 -1
  147. package/dist/notification/notification-group.d.ts +1 -1
  148. package/dist/notification/notification-group2.js +1 -1
  149. package/dist/notification/notification.d.ts +1 -1
  150. package/dist/notification/notification2.js +1 -1
  151. package/dist/page/page-panel/page-panel-content.d.ts +1 -1
  152. package/dist/page/page-panel/page-panel-content2.js +1 -1
  153. package/dist/page/page-panel/page-panel-footer.d.ts +1 -1
  154. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  155. package/dist/page/page-panel/page-panel-header.d.ts +1 -1
  156. package/dist/page/page-panel/page-panel-header2.js +1 -1
  157. package/dist/page/page-panel/page-panel.d.ts +1 -1
  158. package/dist/page/page-panel/page-panel2.js +1 -1
  159. package/dist/page/page.d.ts +1 -1
  160. package/dist/page/page2.js +1 -1
  161. package/dist/page-header/page-header.d.ts +1 -1
  162. package/dist/page-header/page-header2.js +1 -1
  163. package/dist/page-loader/page-loader.d.ts +1 -1
  164. package/dist/page-loader/page-loader2.js +1 -1
  165. package/dist/pagination/pagination.d.ts +1 -1
  166. package/dist/pagination/pagination2.js +1 -1
  167. package/dist/panel/panel.d.ts +4 -4
  168. package/dist/panel/panel2.js +4 -4
  169. package/dist/password/password.d.ts +1 -1
  170. package/dist/password/password2.js +1 -1
  171. package/dist/preferences-input/preferences-input.d.ts +1 -1
  172. package/dist/preferences-input/preferences-input2.js +1 -1
  173. package/dist/progress-bar/progress-bar.d.ts +1 -1
  174. package/dist/progress-bar/progress-bar2.js +1 -1
  175. package/dist/progress-ring/progress-ring.d.ts +1 -1
  176. package/dist/progress-ring/progress-ring2.js +1 -1
  177. package/dist/progressive-filter-chip/progressive-filter-chip.d.ts +1 -1
  178. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  179. package/dist/pulse/pulse.d.ts +1 -1
  180. package/dist/pulse/pulse2.js +1 -1
  181. package/dist/radio/radio-group2.js +1 -1
  182. package/dist/radio/radio2.js +1 -1
  183. package/dist/range/range.d.ts +1 -1
  184. package/dist/range/range2.js +1 -1
  185. package/dist/resize-handle/resize-handle.d.ts +1 -1
  186. package/dist/resize-handle/resize-handle2.js +1 -1
  187. package/dist/search/search.d.ts +1 -1
  188. package/dist/search/search2.js +1 -1
  189. package/dist/select/select.d.ts +2 -2
  190. package/dist/select/select2.js +1 -1
  191. package/dist/skeleton/skeleton.d.ts +1 -1
  192. package/dist/skeleton/skeleton2.js +1 -1
  193. package/dist/sort-button/sort-button.d.ts +1 -1
  194. package/dist/sort-button/sort-button2.js +1 -1
  195. package/dist/sparkline/sparkline.d.ts +1 -1
  196. package/dist/sparkline/sparkline2.js +1 -1
  197. package/dist/star-rating/star-rating.d.ts +1 -1
  198. package/dist/star-rating/star-rating2.js +1 -1
  199. package/dist/steps/steps.d.ts +5 -5
  200. package/dist/steps/steps2.js +2 -2
  201. package/dist/steps/steps2.js.map +1 -1
  202. package/dist/switch/switch-group2.js +1 -1
  203. package/dist/switch/switch2.js +1 -1
  204. package/dist/tabs/tabs-group.d.ts +1 -1
  205. package/dist/tabs/tabs-group2.js +1 -1
  206. package/dist/tabs/tabs.d.ts +2 -2
  207. package/dist/tabs/tabs2.js +2 -2
  208. package/dist/tag/tag.d.ts +1 -1
  209. package/dist/tag/tag2.js +1 -1
  210. package/dist/textarea/textarea.d.ts +2 -2
  211. package/dist/textarea/textarea2.js +1 -1
  212. package/dist/time/time.d.ts +1 -1
  213. package/dist/time/time2.js +1 -1
  214. package/dist/toast/toast.d.ts +1 -1
  215. package/dist/toast/toast2.js +1 -1
  216. package/dist/toggletip/toggletip-footer.d.ts +1 -1
  217. package/dist/toggletip/toggletip-footer2.js +1 -1
  218. package/dist/toggletip/toggletip-header.d.ts +1 -1
  219. package/dist/toggletip/toggletip-header2.js +1 -1
  220. package/dist/toggletip/toggletip.d.ts +1 -1
  221. package/dist/toggletip/toggletip2.js +1 -1
  222. package/dist/toolbar/toolbar.d.ts +1 -1
  223. package/dist/toolbar/toolbar2.js +1 -1
  224. package/dist/tooltip/tooltip.d.ts +1 -1
  225. package/dist/tooltip/tooltip2.js +1 -1
  226. package/dist/tree/tree-node.d.ts +2 -2
  227. package/dist/tree/tree-node2.js +1 -1
  228. package/dist/tree/tree-node2.js.map +1 -1
  229. package/dist/tree/tree.d.ts +2 -1
  230. package/dist/tree/tree2.js +1 -1
  231. package/dist/tree/tree2.js.map +1 -1
  232. package/dist/viewport/define.d.ts +2 -1
  233. package/dist/viewport/define.js +2 -1
  234. package/dist/viewport/define.js.map +1 -1
  235. package/dist/viewport/index.d.ts +2 -1
  236. package/dist/viewport/index.js +2 -1
  237. package/dist/viewport/viewport-gesture-navigation.controller.d.ts +8 -10
  238. package/dist/viewport/viewport-gesture-navigation.controller.js +73 -66
  239. package/dist/viewport/viewport-gesture-navigation.controller.js.map +1 -1
  240. package/dist/viewport/viewport-gridlines.d.ts +1 -1
  241. package/dist/viewport/viewport-gridlines2.js +3 -3
  242. package/dist/viewport/viewport-gridlines2.js.map +1 -1
  243. package/dist/viewport/viewport-minimap.d.ts +36 -0
  244. package/dist/viewport/viewport-minimap.js +6 -0
  245. package/dist/viewport/viewport-minimap.js.map +1 -0
  246. package/dist/viewport/viewport-minimap.utils.d.ts +13 -0
  247. package/dist/viewport/viewport-minimap.utils.js +49 -0
  248. package/dist/viewport/viewport-minimap.utils.js.map +1 -0
  249. package/dist/viewport/viewport-minimap2.js +309 -0
  250. package/dist/viewport/viewport-minimap2.js.map +1 -0
  251. package/dist/viewport/viewport-navigation.controller.d.ts +7 -13
  252. package/dist/viewport/viewport-navigation.controller.js +14 -20
  253. package/dist/viewport/viewport-navigation.controller.js.map +1 -1
  254. package/dist/viewport/viewport-navigation.types.d.ts +0 -8
  255. package/dist/viewport/viewport.d.ts +31 -6
  256. package/dist/viewport/viewport.examples.js.map +1 -1
  257. package/dist/viewport/viewport.examples.json +13 -4
  258. package/dist/viewport/viewport.js +1 -1
  259. package/dist/viewport/viewport.js.map +1 -1
  260. package/dist/viewport/viewport.types.d.ts +50 -23
  261. package/dist/viewport/viewport2.js +173 -118
  262. package/dist/viewport/viewport2.js.map +1 -1
  263. package/dist/week/week.d.ts +1 -1
  264. package/dist/week/week2.js +1 -1
  265. package/package.json +7 -4
@@ -1 +1 @@
1
- {"version":3,"file":"viewport-gesture-navigation.controller.js","names":[],"sources":["../../src/viewport/viewport-gesture-navigation.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport {\n GestureController,\n KeyStateController,\n isImmediateRootActiveElement,\n type Gesture,\n type GestureInput,\n type PinchStart,\n type PointerEndGesture,\n type WheelGestureInput\n} from '@nvidia-elements/core/internal';\nimport type { PointerMovementGesture } from '@nvidia-elements/core/internal';\nimport type {\n ViewportPanBehavior,\n ViewportPanEndDetail,\n ViewportPanEndReason,\n ViewportPoint,\n ViewportPointerPanDetail,\n ViewportTransform,\n ViewportWheelPanDetail,\n ViewportZoomDetail\n} from './viewport.types.js';\nimport type { ViewportNavigationEventDelegate } from './viewport-navigation.types.js';\nimport { anchoredTransform, contentPointFromViewport } from './viewport-projection.utils.js';\n\ntype PointerPanDefaultAction = 'apply' | 'skip';\n\ntype PointerPanLifecycle =\n | { readonly state: 'pending' }\n | { readonly state: 'active'; readonly defaultAction: PointerPanDefaultAction }\n | { readonly state: 'suppressed' };\n\ninterface PointerPanSession {\n readonly button: number;\n readonly dragThreshold: number;\n lastTotalDisplacementX: number;\n lastTotalDisplacementY: number;\n lifecycle: PointerPanLifecycle;\n readonly pointerType: string;\n readonly start: ViewportTransform;\n transformStart: ViewportTransform;\n transformStartDisplacementX: number;\n transformStartDisplacementY: number;\n}\n\ninterface PinchContext {\n readonly anchor: ViewportPoint;\n readonly start: ViewportTransform;\n}\n\ntype ViewportGestureNavigationHost = HTMLElement &\n ReactiveControllerHost & {\n readonly _internals: ElementInternals;\n readonly behaviorPan: ViewportPanBehavior;\n readonly behaviorZoom: boolean;\n readonly dragThreshold: number;\n };\n\nexport interface ViewportGestureNavigationDelegate {\n readonly commitTransform: (next: ViewportTransform) => boolean;\n readonly cancelAnimation: () => void;\n readonly clampScale: (value: number) => number;\n readonly clientToViewport: (clientX: number, clientY: number) => ViewportPoint;\n readonly consumeAutoFit: () => void;\n readonly events: ViewportNavigationEventDelegate;\n readonly getTransform: () => ViewportTransform;\n}\n\n/** Coordinates the viewport's opt-in pointer, touch, pinch, and wheel navigation behavior. */\nexport class ViewportGestureNavigationController implements ReactiveController {\n readonly #host: ViewportGestureNavigationHost;\n readonly #delegate: ViewportGestureNavigationDelegate;\n readonly #gestureController: GestureController<PinchContext>;\n readonly #keyStateController: KeyStateController;\n readonly #pointerPanSessions = new Map<number, PointerPanSession>();\n readonly #suppressedClicks = new Map<\n number,\n { eventType: 'auxclick' | 'click'; timer: ReturnType<typeof setTimeout> }\n >();\n #connected = false;\n #clickListenersActive = false;\n #spaceKeyListenerTarget?: Window;\n #nativeInteractionHovered = false;\n #pinchPointerIds?: ReadonlySet<number>;\n\n constructor(host: ViewportGestureNavigationHost, delegate: ViewportGestureNavigationDelegate) {\n this.#host = host;\n this.#delegate = delegate;\n host.addController(this);\n this.#gestureController = new GestureController(host, {\n beginPinch: this.#beginPinch,\n claimPriority: 'descendant-first',\n shouldIgnoreEvent: this.#shouldIgnoreEvent,\n shouldPreventContextMenu: this.#shouldPreventContextMenu,\n shouldReservePointerDown: this.#shouldReservePointerDown,\n suppressNativeDrag: true,\n touchAction: this.#getTouchAction\n });\n this.#keyStateController = new KeyStateController(host, { watchedCodes: ['Space'] });\n }\n\n hostConnected(): void {\n this.#connected = true;\n this.#host.addEventListener('nve-gesture', this.#handleGesture as EventListener);\n this.#host.addEventListener('nve-gesture-input', this.#handleGestureInput as EventListener);\n this.#host.addEventListener('blur', this.#handleBlur);\n this.#host.addEventListener('focus', this.#handleFocus);\n this.#host.addEventListener('pointerover', this.#handlePointerOver as EventListener);\n this.#syncBehaviorPolicy();\n }\n\n hostDisconnected(): void {\n this.#connected = false;\n this.#keyStateController.enabled = false;\n this.#gestureController.target = undefined;\n this.#host.removeEventListener('nve-gesture', this.#handleGesture as EventListener);\n this.#host.removeEventListener('nve-gesture-input', this.#handleGestureInput as EventListener);\n this.#host.removeEventListener('blur', this.#handleBlur);\n this.#host.removeEventListener('focus', this.#handleFocus);\n this.#host.removeEventListener('pointerover', this.#handlePointerOver as EventListener);\n this.#setClickListeners(false);\n this.#setSpaceKeyListener(false);\n this.#clearPointerState();\n }\n\n hostUpdated(): void {\n this.#syncBehaviorPolicy();\n this.#syncPanEligibleState();\n }\n\n /** Rebase in-progress pointer math synchronously after an independent transform change. */\n rebasePointerSessions(): void {\n this.#rebasePointerPans();\n }\n\n #syncBehaviorPolicy(): void {\n const panBehavior = this.#host.behaviorPan;\n const zoomBehavior = this.#host.behaviorZoom;\n const behaviorEnabled = Boolean(panBehavior) || zoomBehavior;\n const handlesClaimedPointers = this.#pointerPanSessions.size > 0;\n this.#keyStateController.enabled = this.#connected && panBehavior === 'space';\n this.#gestureController.target =\n this.#connected && (behaviorEnabled || handlesClaimedPointers) ? this.#host : undefined;\n this.#setSpaceKeyListener(this.#connected && panBehavior === 'space');\n this.#setClickListeners(this.#connected && (Boolean(panBehavior) || this.#suppressedClicks.size > 0));\n this.#syncDisabledPanEligibility(panBehavior);\n }\n\n #syncDisabledPanEligibility(panBehavior: ViewportPanBehavior): void {\n if (panBehavior) return;\n this.#nativeInteractionHovered = false;\n this.#host._internals?.states.delete('pan-eligible');\n }\n\n #handleGestureInput = (event: CustomEvent<GestureInput>): void => {\n const input = event.detail;\n if (input.kind === 'pointerdown') {\n this.#handlePointerDown(input);\n } else if (input.kind === 'pointerend') {\n this.#handlePointerEnd(input);\n } else {\n this.#handleWheel(input);\n }\n };\n\n #handlePointerDown(input: Extract<GestureInput, { kind: 'pointerdown' }>): void {\n const nativeEvent = input.event;\n this.#clearSuppressedClick(nativeEvent.pointerId);\n const isTouch = nativeEvent.pointerType === 'touch';\n const canPan = isTouch ? Boolean(this.#host.behaviorPan) : this.#acceptsPointerPan(nativeEvent);\n const canPinch = isTouch && this.#host.behaviorZoom;\n if (!canPan && !canPinch) return this.#focusSpaceViewportFromUnclaimedPointer(nativeEvent);\n const claimed = input.claim({ kind: canPan ? 'pan' : undefined, pinchCandidate: canPinch });\n if (!claimed) return;\n if (!isTouch) this.#host.focus({ preventScroll: true });\n if (nativeEvent.button === 1) nativeEvent.preventDefault();\n this.#delegate.consumeAutoFit();\n const start = this.#delegate.getTransform();\n this.#pointerPanSessions.set(nativeEvent.pointerId, {\n button: nativeEvent.button,\n dragThreshold: this.#host.dragThreshold,\n lastTotalDisplacementX: 0,\n lastTotalDisplacementY: 0,\n lifecycle: canPan ? { state: 'pending' } : { state: 'suppressed' },\n pointerType: nativeEvent.pointerType,\n start,\n transformStart: start,\n transformStartDisplacementX: 0,\n transformStartDisplacementY: 0\n });\n }\n\n #focusSpaceViewportFromUnclaimedPointer(event: PointerEvent): void {\n if (this.#host.behaviorPan !== 'space' || event.pointerType === 'touch' || event.button !== 0) return;\n this.#host.focus({ preventScroll: true });\n }\n\n #handlePointerEnd(input: PointerEndGesture): void {\n const pointerId = input.event.pointerId;\n const session = this.#pointerPanSessions.get(pointerId);\n const endedPinch = this.#endPinchIfNeeded(pointerId);\n if (session) this.#finishPointerPan(input, session, endedPinch);\n if (session && this.#pointerPanSessions.get(pointerId) === session) this.#pointerPanSessions.delete(pointerId);\n this.#syncPanningState();\n this.#syncBehaviorPolicy();\n }\n\n #endPinchIfNeeded(pointerId: number): boolean {\n if (!this.#pinchPointerIds?.has(pointerId)) return false;\n for (const [candidatePointerId, candidate] of this.#pointerPanSessions) {\n if (candidatePointerId !== pointerId && candidate.pointerType === 'touch') {\n this.#suppressPointerPan(candidate);\n }\n }\n this.#pinchPointerIds = undefined;\n return true;\n }\n\n #finishPointerPan(input: PointerEndGesture, session: PointerPanSession, endedPinch: boolean): void {\n if (session.lifecycle.state !== 'active') return;\n this.#suppressPointerPan(session);\n this.#syncPanningState();\n const interrupted = input.interrupted || endedPinch;\n this.#dispatchPanEnd(input, session, interrupted);\n if (\n !interrupted &&\n this.#getAuthoritativePointerPanLifecycle(input.event.pointerId, session)?.state === 'suppressed'\n ) {\n this.#queueClickSuppression(input.event.pointerId, session);\n }\n }\n\n #handleWheel(input: WheelGestureInput): void {\n if (!isImmediateRootActiveElement(this.#host)) return;\n if (input.event.ctrlKey || input.event.metaKey) {\n this.#handleWheelZoom(input);\n } else {\n this.#handleWheelPan(input);\n }\n }\n\n #handleWheelZoom(input: WheelGestureInput): void {\n if (!this.#host.behaviorZoom || !input.claim()) return;\n this.#delegate.consumeAutoFit();\n this.#delegate.cancelAnimation();\n const start = this.#delegate.getTransform();\n const viewport = this.#delegate.clientToViewport(input.clientX, input.clientY);\n const anchor = contentPointFromViewport(viewport.x, viewport.y, start);\n const factor = this.#gestureController.getWheelZoomFactor(input);\n const next = anchoredTransform(anchor, viewport, this.#delegate.clampScale(start.scale * factor));\n const detail: ViewportZoomDetail = {\n anchor,\n clientX: input.clientX,\n clientY: input.clientY,\n event: input.event,\n factor,\n next,\n source: 'wheel',\n start\n };\n if (this.#delegate.events.dispatchZoom(detail) && this.#delegate.commitTransform(next)) {\n this.rebasePointerSessions();\n }\n }\n\n #handleWheelPan(input: WheelGestureInput): void {\n if (!this.#host.behaviorPan || !input.claim()) return;\n this.#delegate.consumeAutoFit();\n this.#delegate.cancelAnimation();\n const start = this.#delegate.getTransform();\n const next = {\n scale: start.scale,\n x: start.x + input.deltaX / start.scale,\n y: start.y + input.deltaY / start.scale\n };\n const detail: ViewportWheelPanDetail = {\n clientX: input.clientX,\n clientY: input.clientY,\n deltaX: input.deltaX,\n deltaY: input.deltaY,\n event: input.event,\n next,\n source: 'wheel',\n start\n };\n if (this.#delegate.events.dispatchPan(detail) && this.#delegate.commitTransform(next)) {\n this.rebasePointerSessions();\n }\n }\n\n #handleGesture = (event: CustomEvent<Gesture<PinchContext>>): void => {\n const gesture = event.detail;\n if (gesture.kind === 'pinch') {\n this.#handlePinchGesture(gesture);\n } else if (gesture.kind === 'pan') {\n this.#handlePointerPan(gesture);\n }\n };\n\n #handlePointerPan(gesture: PointerMovementGesture & { readonly kind: 'pan' }): void {\n const pointerId = gesture.event.pointerId;\n const session = this.#pointerPanSessions.get(pointerId);\n if (!session || session.lifecycle.state === 'suppressed') return;\n session.lastTotalDisplacementX = gesture.totalDisplacementX;\n session.lastTotalDisplacementY = gesture.totalDisplacementY;\n if (session.lifecycle.state === 'pending' && !this.#activatePendingPan(pointerId, session, gesture)) return;\n const lifecycle = session.lifecycle;\n if (lifecycle.state !== 'active') return;\n this.#delegate.cancelAnimation();\n const displacementX = gesture.totalDisplacementX - session.transformStartDisplacementX;\n const displacementY = gesture.totalDisplacementY - session.transformStartDisplacementY;\n const next = {\n scale: session.transformStart.scale,\n x: session.transformStart.x - displacementX / session.transformStart.scale,\n y: session.transformStart.y - displacementY / session.transformStart.scale\n };\n const detail: ViewportPointerPanDetail = { ...gesture, next, source: 'pointer', start: session.start };\n this.#dispatchPointerPanAndApplyDefault(pointerId, session, detail);\n }\n\n #dispatchPointerPanAndApplyDefault(\n pointerId: number,\n session: PointerPanSession,\n detail: ViewportPointerPanDetail\n ): void {\n const appliesPanDefault = this.#delegate.events.dispatchPan(detail);\n const authoritativeLifecycle = this.#getAuthoritativePointerPanLifecycle(pointerId, session);\n if (\n appliesPanDefault &&\n authoritativeLifecycle?.state === 'active' &&\n authoritativeLifecycle.defaultAction === 'apply'\n ) {\n this.#delegate.commitTransform(detail.next);\n }\n }\n\n #activatePendingPan(pointerId: number, session: PointerPanSession, gesture: PointerMovementGesture): boolean {\n if (session.lifecycle.state !== 'pending') return false;\n const distanceSquared = gesture.totalDisplacementX ** 2 + gesture.totalDisplacementY ** 2;\n if (distanceSquared < session.dragThreshold ** 2) return false;\n const displacementX = gesture.totalDisplacementX - session.transformStartDisplacementX;\n const displacementY = gesture.totalDisplacementY - session.transformStartDisplacementY;\n const next = {\n scale: session.transformStart.scale,\n x: session.transformStart.x - displacementX / session.transformStart.scale,\n y: session.transformStart.y - displacementY / session.transformStart.scale\n };\n const detail: ViewportPointerPanDetail = { ...gesture, next, source: 'pointer', start: session.start };\n const defaultAction: PointerPanDefaultAction = this.#delegate.events.dispatchPanStart(detail) ? 'apply' : 'skip';\n if (this.#getAuthoritativePointerPanLifecycle(pointerId, session)?.state !== 'pending') return false;\n session.lifecycle = { defaultAction, state: 'active' };\n this.#syncPanningState();\n return true;\n }\n\n #getAuthoritativePointerPanLifecycle(pointerId: number, session: PointerPanSession): PointerPanLifecycle | undefined {\n const authoritativeSession = this.#pointerPanSessions.get(pointerId);\n return authoritativeSession === session ? authoritativeSession.lifecycle : undefined;\n }\n\n #handlePinchGesture(gesture: Extract<Gesture<PinchContext>, { kind: 'pinch' }>): void {\n this.#delegate.cancelAnimation();\n this.#interruptPointerPansForPinch(gesture.event);\n const viewport = this.#delegate.clientToViewport(gesture.centerClientX, gesture.centerClientY);\n const nextScale = this.#delegate.clampScale(gesture.context.start.scale * gesture.scale);\n const next = anchoredTransform(gesture.context.anchor, viewport, nextScale);\n const detail: ViewportZoomDetail = {\n anchor: gesture.context.anchor,\n clientX: gesture.centerClientX,\n clientY: gesture.centerClientY,\n event: gesture.event,\n factor: gesture.scale,\n next,\n source: 'pinch',\n start: gesture.context.start\n };\n if (this.#delegate.events.dispatchZoom(detail) && this.#delegate.commitTransform(next)) {\n this.rebasePointerSessions();\n }\n }\n\n #beginPinch = (pinch: PinchStart): { context: PinchContext } | undefined => {\n const start = this.#delegate.getTransform();\n const viewport = this.#delegate.clientToViewport(pinch.startCenterClientX, pinch.startCenterClientY);\n const context: PinchContext = {\n anchor: contentPointFromViewport(viewport.x, viewport.y, start),\n start\n };\n this.#pinchPointerIds = new Set([pinch.firstPointerId, pinch.secondPointerId]);\n return { context };\n };\n\n #interruptPointerPansForPinch(event: PointerEvent): void {\n const pinchPointerIds = this.#pinchPointerIds;\n if (!pinchPointerIds) return;\n for (const pointerId of pinchPointerIds) {\n const session = this.#pointerPanSessions.get(pointerId);\n if (!session) continue;\n this.#interruptPointerPan({ event, reason: 'pinch' }, session);\n }\n this.#syncPanningState();\n }\n\n #interruptPointerPan(\n end: { readonly event: PointerEvent; readonly reason: ViewportPanEndReason },\n session: PointerPanSession\n ): void {\n const wasActive = session.lifecycle.state === 'active';\n this.#suppressPointerPan(session);\n if (wasActive) this.#dispatchPanEnd(end, session, true);\n }\n\n #suppressPointerPan(session: PointerPanSession): void {\n if (session.lifecycle.state === 'suppressed') return;\n session.lifecycle = { state: 'suppressed' };\n }\n\n #dispatchPanEnd(\n end: { readonly event: PointerEvent; readonly reason: ViewportPanEndReason },\n session: PointerPanSession,\n interrupted: boolean\n ): void {\n const detail: ViewportPanEndDetail = {\n event: end.event,\n interrupted,\n reason: end.reason,\n source: 'pointer',\n start: session.start,\n transform: this.#delegate.getTransform()\n };\n this.#delegate.events.dispatchPanEnd(detail);\n }\n\n #handleSpaceKeyDown = (event: KeyboardEvent): void => {\n if (event.code !== 'Space' || this.#host.behaviorPan !== 'space') return;\n if (!isImmediateRootActiveElement(this.#host)) return;\n event.preventDefault();\n };\n\n #handleFocus = (): void => {\n this.#syncPanEligibleState();\n };\n\n #handleBlur = (): void => {\n this.#host._internals.states.delete('pan-eligible');\n };\n\n #handlePointerOver = (event: PointerEvent): void => {\n if (!this.#host.behaviorPan) return;\n this.#nativeInteractionHovered = eventTargetsNativeInteraction(event, this.#host);\n this.#syncPanEligibleState();\n };\n\n #acceptsPointerPan(event: PointerEvent): boolean {\n if (event.button === 0) {\n return this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible());\n }\n if (event.button === 1) return Boolean(this.#host.behaviorPan);\n return false;\n }\n\n #isSpacePanEligible(): boolean {\n return this.#keyStateController.isPressed('Space') && isImmediateRootActiveElement(this.#host);\n }\n\n #shouldIgnoreEvent = (event: Event): boolean => {\n if (event.type === 'dragstart' && !this.#host.behaviorPan) return true;\n return eventTargetsNativeInteraction(event, this.#host);\n };\n\n #shouldPreventContextMenu = (event: MouseEvent): boolean => {\n if (!event.ctrlKey) return false;\n return this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible());\n };\n\n #shouldReservePointerDown = (event: PointerEvent): boolean =>\n this.#host.behaviorPan === 'space' &&\n this.#isSpacePanEligible() &&\n (event.pointerType === 'mouse' || event.pointerType === 'pen') &&\n event.button === 0;\n\n #getTouchAction = (): string | undefined =>\n this.#host.behaviorPan || this.#host.behaviorZoom || this.#pointerPanSessions.size > 0 ? 'none' : undefined;\n\n #rebasePointerPans(): void {\n const transformStart = this.#delegate.getTransform();\n for (const session of this.#pointerPanSessions.values()) {\n this.#rebaseEligiblePointerPan(session, transformStart);\n }\n }\n\n #rebaseEligiblePointerPan(session: PointerPanSession, transformStart: ViewportTransform): void {\n if (session.lifecycle.state === 'suppressed') return;\n session.transformStart = transformStart;\n session.transformStartDisplacementX = session.lastTotalDisplacementX;\n session.transformStartDisplacementY = session.lastTotalDisplacementY;\n }\n\n #handleClickCapture = (event: PointerEvent): void => {\n const suppression = this.#suppressedClicks.get(event.pointerId);\n if (!suppression || suppression.eventType !== event.type) return;\n this.#clearSuppressedClick(event.pointerId);\n this.#syncBehaviorPolicy();\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n #queueClickSuppression(pointerId: number, session: PointerPanSession): void {\n const eventType = session.pointerType === 'touch' || session.button === 0 ? 'click' : 'auxclick';\n this.#clearSuppressedClick(pointerId);\n const timer = globalThis.setTimeout(() => {\n this.#clearSuppressedClick(pointerId);\n this.#syncBehaviorPolicy();\n });\n this.#suppressedClicks.set(pointerId, { eventType, timer });\n this.#setClickListeners(true);\n }\n\n #clearSuppressedClick(pointerId: number): void {\n const suppression = this.#suppressedClicks.get(pointerId);\n if (!suppression) return;\n clearTimeout(suppression.timer);\n this.#suppressedClicks.delete(pointerId);\n }\n\n #clearPointerState(): void {\n this.#pointerPanSessions.clear();\n this.#pinchPointerIds = undefined;\n for (const pointerId of this.#suppressedClicks.keys()) this.#clearSuppressedClick(pointerId);\n this.#syncPanningState();\n }\n\n #syncPanningState(): void {\n const panning = [...this.#pointerPanSessions.values()].some(session => session.lifecycle.state === 'active');\n if (panning) this.#host._internals.states.add('panning');\n else this.#host._internals.states.delete('panning');\n }\n\n #syncPanEligibleState(): void {\n const eligible =\n !this.#nativeInteractionHovered &&\n (this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible()));\n if (eligible) this.#host._internals.states.add('pan-eligible');\n else this.#host._internals.states.delete('pan-eligible');\n }\n\n #setSpaceKeyListener(enabled: boolean): void {\n const target = enabled ? (this.#host.ownerDocument.defaultView ?? undefined) : undefined;\n if (target === this.#spaceKeyListenerTarget) return;\n this.#spaceKeyListenerTarget?.removeEventListener('keydown', this.#handleSpaceKeyDown as EventListener);\n this.#spaceKeyListenerTarget = target;\n this.#spaceKeyListenerTarget?.addEventListener('keydown', this.#handleSpaceKeyDown as EventListener);\n }\n\n #setClickListeners(enabled: boolean): void {\n if (enabled === this.#clickListenersActive) return;\n this.#clickListenersActive = enabled;\n if (enabled) {\n this.#host.addEventListener('click', this.#handleClickCapture as EventListener, true);\n this.#host.addEventListener('auxclick', this.#handleClickCapture as EventListener, true);\n } else {\n this.#host.removeEventListener('click', this.#handleClickCapture as EventListener, true);\n this.#host.removeEventListener('auxclick', this.#handleClickCapture as EventListener, true);\n }\n }\n}\n\nfunction eventTargetsNativeInteraction(event: Event, boundary: Element): boolean {\n for (const target of event.composedPath()) {\n if (target === boundary) break;\n if (!(target instanceof Element)) continue;\n if (isNativeInteractionElement(target)) return true;\n }\n return false;\n}\n\nfunction isNativeInteractionElement(element: Element): boolean {\n return (\n element.matches('button, input, textarea, select, a[href], [contenteditable], [tabindex]') ||\n isFormAssociatedCustomElement(element)\n );\n}\n\nfunction isFormAssociatedCustomElement(element: Element): boolean {\n if (!element.localName.includes('-')) return false;\n return (element.constructor as typeof HTMLElement & { formAssociated?: boolean }).formAssociated === true;\n}\n"],"mappings":";;;;;AAwEA,IAAa,IAAb,MAA+E;CAC7E;CACA;CACA;CACA;CACA,qBAA+B,IAAI,IAA+B;CAClE,qBAA6B,IAAI,IAG/B;CACF,KAAa;CACb,KAAwB;CACxB;CACA,KAA4B;CAC5B;CAEA,YAAY,GAAqC,GAA6C;EAa5F,AAZA,KAAK,KAAQ,GACb,KAAK,KAAY,GACjB,EAAK,cAAc,IAAI,GACvB,KAAK,KAAqB,IAAI,EAAkB,GAAM;GACpD,YAAY,KAAK;GACjB,eAAe;GACf,mBAAmB,KAAK;GACxB,0BAA0B,KAAK;GAC/B,0BAA0B,KAAK;GAC/B,oBAAoB;GACpB,aAAa,KAAK;EACpB,CAAC,GACD,KAAK,KAAsB,IAAI,EAAmB,GAAM,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC;CACrF;CAEA,gBAAsB;EAOpB,AANA,KAAK,KAAa,IAClB,KAAK,GAAM,iBAAiB,eAAe,KAAK,EAA+B,GAC/E,KAAK,GAAM,iBAAiB,qBAAqB,KAAK,EAAoC,GAC1F,KAAK,GAAM,iBAAiB,QAAQ,KAAK,EAAW,GACpD,KAAK,GAAM,iBAAiB,SAAS,KAAK,EAAY,GACtD,KAAK,GAAM,iBAAiB,eAAe,KAAK,EAAmC,GACnF,KAAK,GAAoB;CAC3B;CAEA,mBAAyB;EAWvB,AAVA,KAAK,KAAa,IAClB,KAAK,GAAoB,UAAU,IACnC,KAAK,GAAmB,SAAS,KAAA,GACjC,KAAK,GAAM,oBAAoB,eAAe,KAAK,EAA+B,GAClF,KAAK,GAAM,oBAAoB,qBAAqB,KAAK,EAAoC,GAC7F,KAAK,GAAM,oBAAoB,QAAQ,KAAK,EAAW,GACvD,KAAK,GAAM,oBAAoB,SAAS,KAAK,EAAY,GACzD,KAAK,GAAM,oBAAoB,eAAe,KAAK,EAAmC,GACtF,KAAK,GAAmB,EAAK,GAC7B,KAAK,GAAqB,EAAK,GAC/B,KAAK,GAAmB;CAC1B;CAEA,cAAoB;EAElB,AADA,KAAK,GAAoB,GACzB,KAAK,GAAsB;CAC7B;CAGA,wBAA8B;EAC5B,KAAK,GAAmB;CAC1B;CAEA,KAA4B;EAC1B,IAAM,IAAc,KAAK,GAAM,aACzB,IAAe,KAAK,GAAM,cAC1B,IAAkB,EAAQ,KAAgB,GAC1C,IAAyB,KAAK,GAAoB,OAAO;EAM/D,AALA,KAAK,GAAoB,UAAU,KAAK,MAAc,MAAgB,SACtE,KAAK,GAAmB,SACtB,KAAK,OAAe,KAAmB,KAA0B,KAAK,KAAQ,KAAA,GAChF,KAAK,GAAqB,KAAK,MAAc,MAAgB,OAAO,GACpE,KAAK,GAAmB,KAAK,OAAe,EAAQ,KAAgB,KAAK,GAAkB,OAAO,EAAE,GACpG,KAAK,GAA4B,CAAW;CAC9C;CAEA,GAA4B,GAAwC;EAC9D,MACJ,KAAK,KAA4B,IACjC,KAAK,GAAM,YAAY,OAAO,OAAO,cAAc;CACrD;CAEA,MAAuB,MAA2C;EAChE,IAAM,IAAQ,EAAM;EACpB,AAAI,EAAM,SAAS,gBACjB,KAAK,GAAmB,CAAK,IACpB,EAAM,SAAS,eACxB,KAAK,GAAkB,CAAK,IAE5B,KAAK,GAAa,CAAK;CAE3B;CAEA,GAAmB,GAA6D;EAC9E,IAAM,IAAc,EAAM;EAC1B,KAAK,GAAsB,EAAY,SAAS;EAChD,IAAM,IAAU,EAAY,gBAAgB,SACtC,IAAS,IAAU,EAAQ,KAAK,GAAM,cAAe,KAAK,GAAmB,CAAW,GACxF,IAAW,KAAW,KAAK,GAAM;EACvC,IAAI,CAAC,KAAU,CAAC,GAAU,OAAO,KAAK,GAAwC,CAAW;EAEzF,IAAI,CADY,EAAM,MAAM;GAAE,MAAM,IAAS,QAAQ,KAAA;GAAW,gBAAgB;EAAS,CACpF,GAAS;EAGd,AAFK,KAAS,KAAK,GAAM,MAAM,EAAE,eAAe,GAAK,CAAC,GAClD,EAAY,WAAW,KAAG,EAAY,eAAe,GACzD,KAAK,GAAU,eAAe;EAC9B,IAAM,IAAQ,KAAK,GAAU,aAAa;EAC1C,KAAK,GAAoB,IAAI,EAAY,WAAW;GAClD,QAAQ,EAAY;GACpB,eAAe,KAAK,GAAM;GAC1B,wBAAwB;GACxB,wBAAwB;GACxB,WAAW,IAAS,EAAE,OAAO,UAAU,IAAI,EAAE,OAAO,aAAa;GACjE,aAAa,EAAY;GACzB;GACA,gBAAgB;GAChB,6BAA6B;GAC7B,6BAA6B;EAC/B,CAAC;CACH;CAEA,GAAwC,GAA2B;EAC7D,KAAK,GAAM,gBAAgB,WAAW,EAAM,gBAAgB,WAAW,EAAM,WAAW,KAC5F,KAAK,GAAM,MAAM,EAAE,eAAe,GAAK,CAAC;CAC1C;CAEA,GAAkB,GAAgC;EAChD,IAAM,IAAY,EAAM,MAAM,WACxB,IAAU,KAAK,GAAoB,IAAI,CAAS,GAChD,IAAa,KAAK,GAAkB,CAAS;EAInD,AAHI,KAAS,KAAK,GAAkB,GAAO,GAAS,CAAU,GAC1D,KAAW,KAAK,GAAoB,IAAI,CAAS,MAAM,KAAS,KAAK,GAAoB,OAAO,CAAS,GAC7G,KAAK,GAAkB,GACvB,KAAK,GAAoB;CAC3B;CAEA,GAAkB,GAA4B;EAC5C,IAAI,CAAC,KAAK,IAAkB,IAAI,CAAS,GAAG,OAAO;EACnD,KAAK,IAAM,CAAC,GAAoB,MAAc,KAAK,IACjD,AAAI,MAAuB,KAAa,EAAU,gBAAgB,WAChE,KAAK,GAAoB,CAAS;EAItC,OADA,KAAK,KAAmB,KAAA,GACjB;CACT;CAEA,GAAkB,GAA0B,GAA4B,GAA2B;EACjG,IAAI,EAAQ,UAAU,UAAU,UAAU;EAE1C,AADA,KAAK,GAAoB,CAAO,GAChC,KAAK,GAAkB;EACvB,IAAM,IAAc,EAAM,eAAe;EAEzC,AADA,KAAK,GAAgB,GAAO,GAAS,CAAW,GAE9C,CAAC,KACD,KAAK,GAAqC,EAAM,MAAM,WAAW,CAAO,CAAC,EAAE,UAAU,gBAErF,KAAK,GAAuB,EAAM,MAAM,WAAW,CAAO;CAE9D;CAEA,GAAa,GAAgC;EACtC,EAA6B,KAAK,EAAK,MACxC,EAAM,MAAM,WAAW,EAAM,MAAM,UACrC,KAAK,GAAiB,CAAK,IAE3B,KAAK,GAAgB,CAAK;CAE9B;CAEA,GAAiB,GAAgC;EAC/C,IAAI,CAAC,KAAK,GAAM,gBAAgB,CAAC,EAAM,MAAM,GAAG;EAEhD,AADA,KAAK,GAAU,eAAe,GAC9B,KAAK,GAAU,gBAAgB;EAC/B,IAAM,IAAQ,KAAK,GAAU,aAAa,GACpC,IAAW,KAAK,GAAU,iBAAiB,EAAM,SAAS,EAAM,OAAO,GACvE,IAAS,EAAyB,EAAS,GAAG,EAAS,GAAG,CAAK,GAC/D,IAAS,KAAK,GAAmB,mBAAmB,CAAK,GACzD,IAAO,EAAkB,GAAQ,GAAU,KAAK,GAAU,WAAW,EAAM,QAAQ,CAAM,CAAC,GAC1F,IAA6B;GACjC;GACA,SAAS,EAAM;GACf,SAAS,EAAM;GACf,OAAO,EAAM;GACb;GACA;GACA,QAAQ;GACR;EACF;EACA,AAAI,KAAK,GAAU,OAAO,aAAa,CAAM,KAAK,KAAK,GAAU,gBAAgB,CAAI,KACnF,KAAK,sBAAsB;CAE/B;CAEA,GAAgB,GAAgC;EAC9C,IAAI,CAAC,KAAK,GAAM,eAAe,CAAC,EAAM,MAAM,GAAG;EAE/C,AADA,KAAK,GAAU,eAAe,GAC9B,KAAK,GAAU,gBAAgB;EAC/B,IAAM,IAAQ,KAAK,GAAU,aAAa,GACpC,IAAO;GACX,OAAO,EAAM;GACb,GAAG,EAAM,IAAI,EAAM,SAAS,EAAM;GAClC,GAAG,EAAM,IAAI,EAAM,SAAS,EAAM;EACpC,GACM,IAAiC;GACrC,SAAS,EAAM;GACf,SAAS,EAAM;GACf,QAAQ,EAAM;GACd,QAAQ,EAAM;GACd,OAAO,EAAM;GACb;GACA,QAAQ;GACR;EACF;EACA,AAAI,KAAK,GAAU,OAAO,YAAY,CAAM,KAAK,KAAK,GAAU,gBAAgB,CAAI,KAClF,KAAK,sBAAsB;CAE/B;CAEA,MAAkB,MAAoD;EACpE,IAAM,IAAU,EAAM;EACtB,AAAI,EAAQ,SAAS,UACnB,KAAK,GAAoB,CAAO,IACvB,EAAQ,SAAS,SAC1B,KAAK,GAAkB,CAAO;CAElC;CAEA,GAAkB,GAAkE;EAClF,IAAM,IAAY,EAAQ,MAAM,WAC1B,IAAU,KAAK,GAAoB,IAAI,CAAS;EAMtD,IALI,CAAC,KAAW,EAAQ,UAAU,UAAU,iBAC5C,EAAQ,yBAAyB,EAAQ,oBACzC,EAAQ,yBAAyB,EAAQ,oBACrC,EAAQ,UAAU,UAAU,aAAa,CAAC,KAAK,GAAoB,GAAW,GAAS,CAAO,MAChF,EAAQ,UACZ,UAAU,UAAU;EAClC,KAAK,GAAU,gBAAgB;EAC/B,IAAM,IAAgB,EAAQ,qBAAqB,EAAQ,6BACrD,IAAgB,EAAQ,qBAAqB,EAAQ,6BACrD,IAAO;GACX,OAAO,EAAQ,eAAe;GAC9B,GAAG,EAAQ,eAAe,IAAI,IAAgB,EAAQ,eAAe;GACrE,GAAG,EAAQ,eAAe,IAAI,IAAgB,EAAQ,eAAe;EACvE,GACM,IAAmC;GAAE,GAAG;GAAS;GAAM,QAAQ;GAAW,OAAO,EAAQ;EAAM;EACrG,KAAK,GAAmC,GAAW,GAAS,CAAM;CACpE;CAEA,GACE,GACA,GACA,GACM;EACN,IAAM,IAAoB,KAAK,GAAU,OAAO,YAAY,CAAM,GAC5D,IAAyB,KAAK,GAAqC,GAAW,CAAO;EAC3F,AACE,KACA,GAAwB,UAAU,YAClC,EAAuB,kBAAkB,WAEzC,KAAK,GAAU,gBAAgB,EAAO,IAAI;CAE9C;CAEA,GAAoB,GAAmB,GAA4B,GAA0C;EAG3G,IAFI,EAAQ,UAAU,UAAU,aACR,EAAQ,sBAAsB,IAAI,EAAQ,sBAAsB,IAClE,EAAQ,iBAAiB,GAAG,OAAO;EACzD,IAAM,IAAgB,EAAQ,qBAAqB,EAAQ,6BACrD,IAAgB,EAAQ,qBAAqB,EAAQ,6BACrD,IAAO;GACX,OAAO,EAAQ,eAAe;GAC9B,GAAG,EAAQ,eAAe,IAAI,IAAgB,EAAQ,eAAe;GACrE,GAAG,EAAQ,eAAe,IAAI,IAAgB,EAAQ,eAAe;EACvE,GACM,IAAmC;GAAE,GAAG;GAAS;GAAM,QAAQ;GAAW,OAAO,EAAQ;EAAM,GAC/F,IAAyC,KAAK,GAAU,OAAO,iBAAiB,CAAM,IAAI,UAAU;EAI1G,OAHI,KAAK,GAAqC,GAAW,CAAO,CAAC,EAAE,UAAU,cAC7E,EAAQ,YAAY;GAAE;GAAe,OAAO;EAAS,GACrD,KAAK,GAAkB,GAChB;CACT;CAEA,GAAqC,GAAmB,GAA6D;EACnH,IAAM,IAAuB,KAAK,GAAoB,IAAI,CAAS;EACnE,OAAO,MAAyB,IAAU,EAAqB,YAAY,KAAA;CAC7E;CAEA,GAAoB,GAAkE;EAEpF,AADA,KAAK,GAAU,gBAAgB,GAC/B,KAAK,GAA8B,EAAQ,KAAK;EAChD,IAAM,IAAW,KAAK,GAAU,iBAAiB,EAAQ,eAAe,EAAQ,aAAa,GACvF,IAAY,KAAK,GAAU,WAAW,EAAQ,QAAQ,MAAM,QAAQ,EAAQ,KAAK,GACjF,IAAO,EAAkB,EAAQ,QAAQ,QAAQ,GAAU,CAAS,GACpE,IAA6B;GACjC,QAAQ,EAAQ,QAAQ;GACxB,SAAS,EAAQ;GACjB,SAAS,EAAQ;GACjB,OAAO,EAAQ;GACf,QAAQ,EAAQ;GAChB;GACA,QAAQ;GACR,OAAO,EAAQ,QAAQ;EACzB;EACA,AAAI,KAAK,GAAU,OAAO,aAAa,CAAM,KAAK,KAAK,GAAU,gBAAgB,CAAI,KACnF,KAAK,sBAAsB;CAE/B;CAEA,MAAe,MAA6D;EAC1E,IAAM,IAAQ,KAAK,GAAU,aAAa,GACpC,IAAW,KAAK,GAAU,iBAAiB,EAAM,oBAAoB,EAAM,kBAAkB,GAC7F,IAAwB;GAC5B,QAAQ,EAAyB,EAAS,GAAG,EAAS,GAAG,CAAK;GAC9D;EACF;EAEA,OADA,KAAK,qBAAmB,IAAI,IAAI,CAAC,EAAM,gBAAgB,EAAM,eAAe,CAAC,GACtE,EAAE,WAAQ;CACnB;CAEA,GAA8B,GAA2B;EACvD,IAAM,IAAkB,KAAK;EACxB,OACL;QAAK,IAAM,KAAa,GAAiB;IACvC,IAAM,IAAU,KAAK,GAAoB,IAAI,CAAS;IACjD,KACL,KAAK,GAAqB;KAAE;KAAO,QAAQ;IAAQ,GAAG,CAAO;GAC/D;GACA,KAAK,GAAkB;EADvB;CAEF;CAEA,GACE,GACA,GACM;EACN,IAAM,IAAY,EAAQ,UAAU,UAAU;EAE9C,AADA,KAAK,GAAoB,CAAO,GAC5B,KAAW,KAAK,GAAgB,GAAK,GAAS,EAAI;CACxD;CAEA,GAAoB,GAAkC;EAChD,EAAQ,UAAU,UAAU,iBAChC,EAAQ,YAAY,EAAE,OAAO,aAAa;CAC5C;CAEA,GACE,GACA,GACA,GACM;EACN,IAAM,IAA+B;GACnC,OAAO,EAAI;GACX;GACA,QAAQ,EAAI;GACZ,QAAQ;GACR,OAAO,EAAQ;GACf,WAAW,KAAK,GAAU,aAAa;EACzC;EACA,KAAK,GAAU,OAAO,eAAe,CAAM;CAC7C;CAEA,MAAuB,MAA+B;EAChD,EAAM,SAAS,WAAW,KAAK,GAAM,gBAAgB,WACpD,EAA6B,KAAK,EAAK,KAC5C,EAAM,eAAe;CACvB;CAEA,WAA2B;EACzB,KAAK,GAAsB;CAC7B;CAEA,WAA0B;EACxB,KAAK,GAAM,WAAW,OAAO,OAAO,cAAc;CACpD;CAEA,MAAsB,MAA8B;EAC7C,KAAK,GAAM,gBAChB,KAAK,KAA4B,EAA8B,GAAO,KAAK,EAAK,GAChF,KAAK,GAAsB;CAC7B;CAEA,GAAmB,GAA8B;EAK/C,OAJI,EAAM,WAAW,IACZ,KAAK,GAAM,gBAAgB,MAAS,KAAK,GAAM,gBAAgB,WAAW,KAAK,GAAoB,IAExG,EAAM,WAAW,KAAU,EAAQ,KAAK,GAAM;CAEpD;CAEA,KAA+B;EAC7B,OAAO,KAAK,GAAoB,UAAU,OAAO,KAAK,EAA6B,KAAK,EAAK;CAC/F;CAEA,MAAsB,MAChB,EAAM,SAAS,eAAe,CAAC,KAAK,GAAM,eACvC,EAA8B,GAAO,KAAK,EAAK;CAGxD,MAA6B,MACtB,EAAM,UACJ,KAAK,GAAM,gBAAgB,MAAS,KAAK,GAAM,gBAAgB,WAAW,KAAK,GAAoB,IAD/E;CAI7B,MAA6B,MAC3B,KAAK,GAAM,gBAAgB,WAC3B,KAAK,GAAoB,MACxB,EAAM,gBAAgB,WAAW,EAAM,gBAAgB,UACxD,EAAM,WAAW;CAEnB,WACE,KAAK,GAAM,eAAe,KAAK,GAAM,gBAAgB,KAAK,GAAoB,OAAO,IAAI,SAAS,KAAA;CAEpG,KAA2B;EACzB,IAAM,IAAiB,KAAK,GAAU,aAAa;EACnD,KAAK,IAAM,KAAW,KAAK,GAAoB,OAAO,GACpD,KAAK,GAA0B,GAAS,CAAc;CAE1D;CAEA,GAA0B,GAA4B,GAAyC;EACzF,EAAQ,UAAU,UAAU,iBAChC,EAAQ,iBAAiB,GACzB,EAAQ,8BAA8B,EAAQ,wBAC9C,EAAQ,8BAA8B,EAAQ;CAChD;CAEA,MAAuB,MAA8B;EACnD,IAAM,IAAc,KAAK,GAAkB,IAAI,EAAM,SAAS;EAC1D,CAAC,KAAe,EAAY,cAAc,EAAM,SACpD,KAAK,GAAsB,EAAM,SAAS,GAC1C,KAAK,GAAoB,GACzB,EAAM,eAAe,GACrB,EAAM,yBAAyB;CACjC;CAEA,GAAuB,GAAmB,GAAkC;EAC1E,IAAM,IAAY,EAAQ,gBAAgB,WAAW,EAAQ,WAAW,IAAI,UAAU;EACtF,KAAK,GAAsB,CAAS;EACpC,IAAM,IAAQ,WAAW,iBAAiB;GAExC,AADA,KAAK,GAAsB,CAAS,GACpC,KAAK,GAAoB;EAC3B,CAAC;EAED,AADA,KAAK,GAAkB,IAAI,GAAW;GAAE;GAAW;EAAM,CAAC,GAC1D,KAAK,GAAmB,EAAI;CAC9B;CAEA,GAAsB,GAAyB;EAC7C,IAAM,IAAc,KAAK,GAAkB,IAAI,CAAS;EACnD,MACL,aAAa,EAAY,KAAK,GAC9B,KAAK,GAAkB,OAAO,CAAS;CACzC;CAEA,KAA2B;EAEzB,AADA,KAAK,GAAoB,MAAM,GAC/B,KAAK,KAAmB,KAAA;EACxB,KAAK,IAAM,KAAa,KAAK,GAAkB,KAAK,GAAG,KAAK,GAAsB,CAAS;EAC3F,KAAK,GAAkB;CACzB;CAEA,KAA0B;EAExB,AADgB,CAAC,GAAG,KAAK,GAAoB,OAAO,CAAC,CAAC,CAAC,MAAK,MAAW,EAAQ,UAAU,UAAU,QAC/F,IAAS,KAAK,GAAM,WAAW,OAAO,IAAI,SAAS,IAClD,KAAK,GAAM,WAAW,OAAO,OAAO,SAAS;CACpD;CAEA,KAA8B;EAI5B,AAFE,CAAC,KAAK,OACL,KAAK,GAAM,gBAAgB,MAAS,KAAK,GAAM,gBAAgB,WAAW,KAAK,GAAoB,KACxF,KAAK,GAAM,WAAW,OAAO,IAAI,cAAc,IACxD,KAAK,GAAM,WAAW,OAAO,OAAO,cAAc;CACzD;CAEA,GAAqB,GAAwB;EAC3C,IAAM,IAAS,IAAW,KAAK,GAAM,cAAc,eAAe,KAAA,IAAa,KAAA;EAC3E,MAAW,KAAK,OACpB,KAAK,IAAyB,oBAAoB,WAAW,KAAK,EAAoC,GACtG,KAAK,KAA0B,GAC/B,KAAK,IAAyB,iBAAiB,WAAW,KAAK,EAAoC;CACrG;CAEA,GAAmB,GAAwB;EACrC,MAAY,KAAK,OACrB,KAAK,KAAwB,GACzB,KACF,KAAK,GAAM,iBAAiB,SAAS,KAAK,IAAsC,EAAI,GACpF,KAAK,GAAM,iBAAiB,YAAY,KAAK,IAAsC,EAAI,MAEvF,KAAK,GAAM,oBAAoB,SAAS,KAAK,IAAsC,EAAI,GACvF,KAAK,GAAM,oBAAoB,YAAY,KAAK,IAAsC,EAAI;CAE9F;AACF;AAEA,SAAS,EAA8B,GAAc,GAA4B;CAC/E,KAAK,IAAM,KAAU,EAAM,aAAa,GAAG;EACzC,IAAI,MAAW,GAAU;EACnB,iBAAkB,WACpB,EAA2B,CAAM,GAAG,OAAO;CACjD;CACA,OAAO;AACT;AAEA,SAAS,EAA2B,GAA2B;CAC7D,OACE,EAAQ,QAAQ,yEAAyE,KACzF,EAA8B,CAAO;AAEzC;AAEA,SAAS,EAA8B,GAA2B;CAEhE,OADK,EAAQ,UAAU,SAAS,GAAG,IAC3B,EAAQ,YAAkE,mBAAmB,KADxD;AAE/C"}
1
+ {"version":3,"file":"viewport-gesture-navigation.controller.js","names":[],"sources":["../../src/viewport/viewport-gesture-navigation.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport {\n GestureController,\n KeyStateController,\n isImmediateRootActiveElement,\n type Gesture,\n type GestureInput,\n type PinchStart,\n type PointerEndGesture,\n type PointerMovementGesture,\n type WheelGestureInput\n} from '@nvidia-elements/core/internal';\nimport type {\n ViewportPanBehavior,\n ViewportPanSession,\n ViewportPanProposal,\n ViewportPanUpdateProposal,\n ViewportPanEndRequest,\n ViewportPanEndReason,\n ViewportPoint,\n ViewportTransform,\n ViewportZoomProposal\n} from './viewport.types.js';\nimport { anchoredTransform, contentPointFromViewport } from './viewport-projection.utils.js';\n\ntype PointerPanLifecycle =\n | { readonly state: 'pending' }\n | { readonly state: 'active'; readonly navigation: ViewportPanSession }\n | { readonly state: 'suppressed' };\n\ninterface PointerPanSession {\n readonly button: number;\n readonly dragThreshold: number;\n lastTotalDisplacementX: number;\n lastTotalDisplacementY: number;\n lifecycle: PointerPanLifecycle;\n pendingEnd?: ViewportPanEndRequest;\n readonly pointerType: string;\n readonly start: ViewportTransform;\n transformStart: ViewportTransform;\n transformStartDisplacementX: number;\n transformStartDisplacementY: number;\n}\n\ninterface PinchContext {\n readonly anchor: ViewportPoint;\n readonly start: ViewportTransform;\n}\n\ntype ViewportGestureNavigationHost = HTMLElement &\n ReactiveControllerHost & {\n readonly _internals: ElementInternals;\n readonly behaviorPan: ViewportPanBehavior;\n readonly pannable: boolean;\n readonly zoomable: boolean;\n readonly dragThreshold: number;\n requestPan(proposal: ViewportPanProposal): boolean;\n requestZoom(proposal: ViewportZoomProposal): boolean;\n startPan(proposal: ViewportPanProposal): ViewportPanSession | undefined;\n };\n\ninterface ViewportGestureNavigationDelegate {\n readonly clampScale: (value: number) => number;\n readonly clientToViewport: (clientX: number, clientY: number) => ViewportPoint;\n readonly getTransform: () => ViewportTransform;\n readonly requestAdmittedPinchZoom: (proposal: ViewportZoomProposal) => boolean;\n}\n\nexport class ViewportGestureNavigationController implements ReactiveController {\n readonly #host: ViewportGestureNavigationHost;\n readonly #delegate: ViewportGestureNavigationDelegate;\n readonly #gestureController: GestureController<PinchContext>;\n readonly #keyStateController: KeyStateController;\n readonly #pointerPanSessions = new Map<number, PointerPanSession>();\n readonly #suppressedClicks = new Map<\n number,\n { eventType: 'auxclick' | 'click'; timer: ReturnType<typeof setTimeout> }\n >();\n #connected = false;\n #clickListenersActive = false;\n #spaceKeyListenerTarget?: Window;\n #nativeInteractionHovered = false;\n #pinchPointerIds?: ReadonlySet<number>;\n\n constructor(host: ViewportGestureNavigationHost, delegate: ViewportGestureNavigationDelegate) {\n this.#host = host;\n this.#delegate = delegate;\n host.addController(this);\n this.#gestureController = new GestureController(host, {\n beginPinch: this.#beginPinch,\n claimPriority: 'descendant-first',\n shouldIgnoreEvent: this.#shouldIgnoreEvent,\n shouldPreventContextMenu: this.#shouldPreventContextMenu,\n shouldReservePointerDown: this.#shouldReservePointerDown,\n suppressNativeDrag: true,\n touchAction: this.#getTouchAction\n });\n this.#keyStateController = new KeyStateController(host, { watchedCodes: ['Space'] });\n }\n\n hostConnected(): void {\n this.#connected = true;\n this.#host.addEventListener('nve-gesture', this.#handleGesture as EventListener);\n this.#host.addEventListener('nve-gesture-input', this.#handleGestureInput as EventListener);\n this.#host.addEventListener('blur', this.#handleBlur);\n this.#host.addEventListener('focus', this.#handleFocus);\n this.#host.addEventListener('pointerover', this.#handlePointerOver as EventListener);\n this.#syncBehaviorPolicy();\n }\n\n hostDisconnected(): void {\n this.#connected = false;\n this.#keyStateController.enabled = false;\n this.#gestureController.target = undefined;\n this.#host.removeEventListener('nve-gesture', this.#handleGesture as EventListener);\n this.#host.removeEventListener('nve-gesture-input', this.#handleGestureInput as EventListener);\n this.#host.removeEventListener('blur', this.#handleBlur);\n this.#host.removeEventListener('focus', this.#handleFocus);\n this.#host.removeEventListener('pointerover', this.#handlePointerOver as EventListener);\n this.#setClickListeners(false);\n this.#setSpaceKeyListener(false);\n this.#clearPointerState();\n }\n\n hostUpdated(): void {\n this.#syncBehaviorPolicy();\n this.#syncPanEligibleState();\n }\n\n rebasePointerSessions(): void {\n this.#rebasePointerPans();\n }\n\n #syncBehaviorPolicy(): void {\n const panBehavior = this.#host.behaviorPan;\n const behaviorEnabled = this.#host.pannable || this.#host.zoomable;\n const handlesClaimedPointers = this.#pointerPanSessions.size > 0;\n this.#keyStateController.enabled = this.#connected && panBehavior === 'space';\n this.#gestureController.target =\n this.#connected && (behaviorEnabled || handlesClaimedPointers) ? this.#host : undefined;\n this.#setSpaceKeyListener(this.#connected && panBehavior === 'space');\n this.#setClickListeners(this.#connected && (this.#host.pannable || this.#suppressedClicks.size > 0));\n this.#syncDisabledPanEligibility();\n }\n\n #syncDisabledPanEligibility(): void {\n if (this.#host.pannable) return;\n this.#nativeInteractionHovered = false;\n this.#host._internals?.states.delete('pan-eligible');\n }\n\n #handleGestureInput = (event: CustomEvent<GestureInput>): void => {\n const input = event.detail;\n if (input.kind === 'pointerdown') {\n this.#handlePointerDown(input);\n } else if (input.kind === 'pointerend') {\n this.#handlePointerEnd(input);\n } else {\n this.#handleWheel(input);\n }\n };\n\n #handlePointerDown(input: Extract<GestureInput, { kind: 'pointerdown' }>): void {\n const nativeEvent = input.event;\n this.#clearSuppressedClick(nativeEvent.pointerId);\n const isTouch = nativeEvent.pointerType === 'touch';\n const canPan = isTouch ? this.#host.pannable : this.#acceptsPointerPan(nativeEvent);\n const canPinch = isTouch && this.#host.zoomable;\n if (!canPan && !canPinch) return this.#focusSpaceViewportFromUnclaimedPointer(nativeEvent);\n const claimed = input.claim({ kind: canPan ? 'pan' : undefined, pinchCandidate: canPinch });\n if (!claimed) return;\n if (!isTouch) this.#host.focus({ preventScroll: true });\n if (nativeEvent.button === 1) nativeEvent.preventDefault();\n const start = this.#delegate.getTransform();\n this.#pointerPanSessions.set(nativeEvent.pointerId, {\n button: nativeEvent.button,\n dragThreshold: this.#host.dragThreshold,\n lastTotalDisplacementX: 0,\n lastTotalDisplacementY: 0,\n lifecycle: canPan ? { state: 'pending' } : { state: 'suppressed' },\n pointerType: nativeEvent.pointerType,\n start,\n transformStart: start,\n transformStartDisplacementX: 0,\n transformStartDisplacementY: 0\n });\n }\n\n #focusSpaceViewportFromUnclaimedPointer(event: PointerEvent): void {\n if (this.#host.behaviorPan !== 'space' || event.pointerType === 'touch' || event.button !== 0) return;\n this.#host.focus({ preventScroll: true });\n }\n\n #handlePointerEnd(input: PointerEndGesture): void {\n const pointerId = input.event.pointerId;\n const session = this.#pointerPanSessions.get(pointerId);\n const endedPinch = this.#endPinchIfNeeded(pointerId);\n if (session) this.#finishPointerPan(input, session, endedPinch);\n if (session && this.#pointerPanSessions.get(pointerId) === session) this.#pointerPanSessions.delete(pointerId);\n this.#syncPanningState();\n this.#syncBehaviorPolicy();\n }\n\n #endPinchIfNeeded(pointerId: number): boolean {\n if (!this.#pinchPointerIds?.has(pointerId)) return false;\n for (const [candidatePointerId, candidate] of this.#pointerPanSessions) {\n if (candidatePointerId !== pointerId && candidate.pointerType === 'touch') {\n this.#suppressPointerPan(candidate);\n }\n }\n this.#pinchPointerIds = undefined;\n return true;\n }\n\n #finishPointerPan(input: PointerEndGesture, session: PointerPanSession, endedPinch: boolean): void {\n if (session.lifecycle.state === 'pending') {\n session.pendingEnd = { event: input.event, interrupted: input.interrupted || endedPinch, reason: input.reason };\n return;\n }\n if (session.lifecycle.state !== 'active') return;\n const interrupted = input.interrupted || endedPinch;\n this.#dispatchPanEnd(input, session, interrupted);\n this.#suppressPointerPan(session);\n this.#syncPanningState();\n if (\n !interrupted &&\n this.#getAuthoritativePointerPanLifecycle(input.event.pointerId, session)?.state === 'suppressed'\n ) {\n this.#queueClickSuppression(input.event.pointerId, session);\n }\n }\n\n #handleWheel(input: WheelGestureInput): void {\n if (!isImmediateRootActiveElement(this.#host)) return;\n if (input.event.ctrlKey || input.event.metaKey) {\n this.#handleWheelZoom(input);\n } else {\n this.#handleWheelPan(input);\n }\n }\n\n #handleWheelZoom(input: WheelGestureInput): void {\n if (!this.#host.zoomable || !input.claim()) return;\n const start = this.#delegate.getTransform();\n const viewport = this.#delegate.clientToViewport(input.clientX, input.clientY);\n const anchor = contentPointFromViewport(viewport.x, viewport.y, start);\n const factor = this.#gestureController.getWheelZoomFactor(input);\n const next = anchoredTransform(anchor, viewport, this.#delegate.clampScale(start.scale * factor));\n const proposal: ViewportZoomProposal = {\n anchor,\n clientX: input.clientX,\n clientY: input.clientY,\n event: input.event,\n factor,\n next,\n source: 'wheel'\n };\n this.#host.requestZoom(proposal);\n }\n\n #handleWheelPan(input: WheelGestureInput): void {\n if (!this.#host.pannable || !input.claim()) return;\n const start = this.#delegate.getTransform();\n const next = {\n scale: start.scale,\n x: start.x + input.deltaX / start.scale,\n y: start.y + input.deltaY / start.scale\n };\n const proposal: ViewportPanProposal = {\n clientX: input.clientX,\n clientY: input.clientY,\n deltaX: input.deltaX,\n deltaY: input.deltaY,\n event: input.event,\n next,\n source: 'wheel'\n };\n this.#host.requestPan(proposal);\n }\n\n #handleGesture = (event: CustomEvent<Gesture<PinchContext>>): void => {\n const gesture = event.detail;\n if (gesture.kind === 'pinch') {\n this.#handlePinchGesture(gesture);\n } else if (gesture.kind === 'pan') {\n this.#handlePointerPan(gesture);\n }\n };\n\n #handlePointerPan(gesture: PointerMovementGesture & { readonly kind: 'pan' }): void {\n const pointerId = gesture.event.pointerId;\n const session = this.#pointerPanSessions.get(pointerId);\n if (!session || session.lifecycle.state === 'suppressed') return;\n session.lastTotalDisplacementX = gesture.totalDisplacementX;\n session.lastTotalDisplacementY = gesture.totalDisplacementY;\n const proposal = this.#pointerPanProposal(gesture, session);\n if (session.lifecycle.state === 'pending') this.#activatePointerPan(gesture, session, proposal);\n else session.lifecycle.navigation.update(proposal);\n }\n\n #pointerPanProposal(\n gesture: PointerMovementGesture & { readonly kind: 'pan' },\n session: PointerPanSession\n ): ViewportPanUpdateProposal {\n const displacementX = gesture.totalDisplacementX - session.transformStartDisplacementX;\n const displacementY = gesture.totalDisplacementY - session.transformStartDisplacementY;\n const next = {\n scale: session.transformStart.scale,\n x: session.transformStart.x - displacementX / session.transformStart.scale,\n y: session.transformStart.y - displacementY / session.transformStart.scale\n };\n return { ...gesture, next };\n }\n\n #activatePointerPan(\n gesture: PointerMovementGesture & { readonly kind: 'pan' },\n session: PointerPanSession,\n proposal: ViewportPanUpdateProposal\n ): void {\n const distanceSquared = gesture.totalDisplacementX ** 2 + gesture.totalDisplacementY ** 2;\n if (distanceSquared < session.dragThreshold ** 2) return;\n const navigation = this.#host.startPan({ ...proposal, source: 'pointer' });\n if (!navigation) return;\n if (this.#getAuthoritativePointerPanLifecycle(gesture.event.pointerId, session)?.state !== 'pending') {\n if (session.pendingEnd) navigation.end(session.pendingEnd);\n return;\n }\n session.lifecycle = { state: 'active', navigation };\n this.#syncPanningState();\n }\n\n #getAuthoritativePointerPanLifecycle(pointerId: number, session: PointerPanSession): PointerPanLifecycle | undefined {\n const authoritativeSession = this.#pointerPanSessions.get(pointerId);\n return authoritativeSession === session ? authoritativeSession.lifecycle : undefined;\n }\n\n #handlePinchGesture(gesture: Extract<Gesture<PinchContext>, { kind: 'pinch' }>): void {\n this.#interruptPointerPansForPinch(gesture.event);\n const viewport = this.#delegate.clientToViewport(gesture.centerClientX, gesture.centerClientY);\n const nextScale = this.#delegate.clampScale(gesture.context.start.scale * gesture.scale);\n const next = anchoredTransform(gesture.context.anchor, viewport, nextScale);\n const proposal: ViewportZoomProposal = {\n anchor: gesture.context.anchor,\n clientX: gesture.centerClientX,\n clientY: gesture.centerClientY,\n event: gesture.event,\n factor: gesture.scale,\n next,\n source: 'pinch'\n };\n this.#delegate.requestAdmittedPinchZoom(proposal);\n }\n\n #beginPinch = (pinch: PinchStart): { context: PinchContext } | undefined => {\n if (!this.#host.zoomable) return undefined;\n const start = this.#delegate.getTransform();\n const viewport = this.#delegate.clientToViewport(pinch.startCenterClientX, pinch.startCenterClientY);\n const context: PinchContext = {\n anchor: contentPointFromViewport(viewport.x, viewport.y, start),\n start\n };\n this.#pinchPointerIds = new Set([pinch.firstPointerId, pinch.secondPointerId]);\n return { context };\n };\n\n #interruptPointerPansForPinch(event: PointerEvent): void {\n const pinchPointerIds = this.#pinchPointerIds;\n if (!pinchPointerIds) return;\n for (const pointerId of pinchPointerIds) {\n const session = this.#pointerPanSessions.get(pointerId);\n if (!session) continue;\n this.#interruptPointerPan({ event, reason: 'pinch' }, session);\n }\n this.#syncPanningState();\n }\n\n #interruptPointerPan(\n end: { readonly event: PointerEvent; readonly reason: ViewportPanEndReason },\n session: PointerPanSession\n ): void {\n const wasActive = session.lifecycle.state === 'active';\n if (session.lifecycle.state === 'pending') session.pendingEnd = { ...end, interrupted: true };\n if (wasActive) this.#dispatchPanEnd(end, session, true);\n this.#suppressPointerPan(session);\n }\n\n #suppressPointerPan(session: PointerPanSession): void {\n if (session.lifecycle.state === 'suppressed') return;\n session.lifecycle = { state: 'suppressed' };\n }\n\n #dispatchPanEnd(\n end: { readonly event: PointerEvent; readonly reason: ViewportPanEndReason },\n session: PointerPanSession,\n interrupted: boolean\n ): void {\n if (session.lifecycle.state !== 'active') return;\n session.lifecycle.navigation.end({ event: end.event, interrupted, reason: end.reason });\n }\n\n #handleSpaceKeyDown = (event: KeyboardEvent): void => {\n if (event.code !== 'Space' || this.#host.behaviorPan !== 'space') return;\n if (!isImmediateRootActiveElement(this.#host)) return;\n event.preventDefault();\n };\n\n #handleFocus = (): void => {\n this.#syncPanEligibleState();\n };\n\n #handleBlur = (): void => {\n this.#host._internals.states.delete('pan-eligible');\n };\n\n #handlePointerOver = (event: PointerEvent): void => {\n if (!this.#host.pannable) return;\n this.#nativeInteractionHovered = eventTargetsNativeInteraction(event, this.#host);\n this.#syncPanEligibleState();\n };\n\n #acceptsPointerPan(event: PointerEvent): boolean {\n if (event.button === 0) {\n return this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible());\n }\n if (event.button === 1) return this.#host.pannable;\n return false;\n }\n\n #isSpacePanEligible(): boolean {\n return this.#keyStateController.isPressed('Space') && isImmediateRootActiveElement(this.#host);\n }\n\n #shouldIgnoreEvent = (event: Event): boolean => {\n if (event.type === 'dragstart' && !this.#host.pannable) return true;\n return eventTargetsViewportOverlay(event, this.#host) || eventTargetsNativeInteraction(event, this.#host);\n };\n\n #shouldPreventContextMenu = (event: MouseEvent): boolean => {\n if (!event.ctrlKey) return false;\n return this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible());\n };\n\n #shouldReservePointerDown = (event: PointerEvent): boolean =>\n this.#host.behaviorPan === 'space' &&\n this.#isSpacePanEligible() &&\n (event.pointerType === 'mouse' || event.pointerType === 'pen') &&\n event.button === 0;\n\n #getTouchAction = (): string | undefined =>\n this.#host.pannable || this.#host.zoomable || this.#pointerPanSessions.size > 0 ? 'none' : undefined;\n\n #rebasePointerPans(): void {\n const transformStart = this.#delegate.getTransform();\n for (const session of this.#pointerPanSessions.values()) {\n this.#rebaseEligiblePointerPan(session, transformStart);\n }\n }\n\n #rebaseEligiblePointerPan(session: PointerPanSession, transformStart: ViewportTransform): void {\n if (session.lifecycle.state === 'suppressed') return;\n session.transformStart = transformStart;\n session.transformStartDisplacementX = session.lastTotalDisplacementX;\n session.transformStartDisplacementY = session.lastTotalDisplacementY;\n }\n\n #handleClickCapture = (event: PointerEvent): void => {\n const suppression = this.#suppressedClicks.get(event.pointerId);\n if (!suppression || suppression.eventType !== event.type) return;\n this.#clearSuppressedClick(event.pointerId);\n this.#syncBehaviorPolicy();\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n #queueClickSuppression(pointerId: number, session: PointerPanSession): void {\n const eventType = session.pointerType === 'touch' || session.button === 0 ? 'click' : 'auxclick';\n this.#clearSuppressedClick(pointerId);\n const timer = globalThis.setTimeout(() => {\n this.#clearSuppressedClick(pointerId);\n this.#syncBehaviorPolicy();\n });\n this.#suppressedClicks.set(pointerId, { eventType, timer });\n this.#setClickListeners(true);\n }\n\n #clearSuppressedClick(pointerId: number): void {\n const suppression = this.#suppressedClicks.get(pointerId);\n if (!suppression) return;\n clearTimeout(suppression.timer);\n this.#suppressedClicks.delete(pointerId);\n }\n\n #clearPointerState(): void {\n this.#pointerPanSessions.clear();\n this.#pinchPointerIds = undefined;\n for (const pointerId of this.#suppressedClicks.keys()) this.#clearSuppressedClick(pointerId);\n this.#syncPanningState();\n }\n\n #syncPanningState(): void {\n const panning = [...this.#pointerPanSessions.values()].some(session => session.lifecycle.state === 'active');\n if (panning) this.#host._internals.states.add('panning');\n else this.#host._internals.states.delete('panning');\n }\n\n #syncPanEligibleState(): void {\n const eligible =\n !this.#nativeInteractionHovered &&\n (this.#host.behaviorPan === true || (this.#host.behaviorPan === 'space' && this.#isSpacePanEligible()));\n if (eligible) this.#host._internals.states.add('pan-eligible');\n else this.#host._internals.states.delete('pan-eligible');\n }\n\n #setSpaceKeyListener(enabled: boolean): void {\n const target = enabled ? (this.#host.ownerDocument.defaultView ?? undefined) : undefined;\n if (target === this.#spaceKeyListenerTarget) return;\n this.#spaceKeyListenerTarget?.removeEventListener('keydown', this.#handleSpaceKeyDown as EventListener);\n this.#spaceKeyListenerTarget = target;\n this.#spaceKeyListenerTarget?.addEventListener('keydown', this.#handleSpaceKeyDown as EventListener);\n }\n\n #setClickListeners(enabled: boolean): void {\n if (enabled === this.#clickListenersActive) return;\n this.#clickListenersActive = enabled;\n if (enabled) {\n this.#host.addEventListener('click', this.#handleClickCapture as EventListener, true);\n this.#host.addEventListener('auxclick', this.#handleClickCapture as EventListener, true);\n } else {\n this.#host.removeEventListener('click', this.#handleClickCapture as EventListener, true);\n this.#host.removeEventListener('auxclick', this.#handleClickCapture as EventListener, true);\n }\n }\n}\n\nfunction eventTargetsViewportOverlay(event: Event, boundary: Element): boolean {\n for (const target of event.composedPath()) {\n if (target === boundary) break;\n if (target instanceof Element && target.parentElement === boundary && target.slot === 'overlay') return true;\n }\n return false;\n}\n\nfunction eventTargetsNativeInteraction(event: Event, boundary: Element): boolean {\n for (const target of event.composedPath()) {\n if (target === boundary) break;\n if (!(target instanceof Element)) continue;\n if (isNativeInteractionElement(target)) return true;\n }\n return false;\n}\n\nfunction isNativeInteractionElement(element: Element): boolean {\n return (\n element.matches('button, input, textarea, select, a[href], [contenteditable], [tabindex]') ||\n isFormAssociatedCustomElement(element)\n );\n}\n\nfunction isFormAssociatedCustomElement(element: Element): boolean {\n if (!element.localName.includes('-')) return false;\n return (element.constructor as typeof HTMLElement & { formAssociated?: boolean }).formAssociated === true;\n}\n"],"mappings":"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"}
@@ -34,5 +34,5 @@ export declare class ViewportGridlines extends LitElement {
34
34
  connectedCallback(): void;
35
35
  disconnectedCallback(): void;
36
36
  protected willUpdate(changed: PropertyValues<this>): void;
37
- render(): typeof nothing | import("lit").TemplateResult<1>;
37
+ render(): typeof nothing | import("lit-html").TemplateResult<1>;
38
38
  }
@@ -24,7 +24,7 @@ var h = 10, g = 64, _ = class extends u {
24
24
  static {
25
25
  this.metadata = {
26
26
  tag: "nve-viewport-gridlines",
27
- version: "2.9.0"
27
+ version: "2.11.0"
28
28
  };
29
29
  }
30
30
  #e;
@@ -72,8 +72,8 @@ var h = 10, g = 64, _ = class extends u {
72
72
  }
73
73
  connectedCallback() {
74
74
  super.connectedCallback();
75
- let e = this.parentElement?.closest(a.metadata.tag);
76
- !(e instanceof a) || e !== this.parentElement || (this.#i = e, this.style.setProperty("--_scale", `${e.scale}`), this.#i.addEventListener("viewportchange", this.#s), typeof ResizeObserver < "u" && (this.#a = new ResizeObserver(this.#c), this.#a.observe(e)), this.#u({
75
+ let e = this.parentElement;
76
+ e instanceof a && (this.#i = e, this.style.setProperty("--_scale", `${e.scale}`), this.#i.addEventListener("viewportchange", this.#s), typeof ResizeObserver < "u" && (this.#a = new ResizeObserver(this.#c), this.#a.observe(e)), this.#u({
77
77
  forceCoverage: !0,
78
78
  resetInterval: !0
79
79
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"viewport-gridlines2.js","names":[],"sources":["../../src/viewport/viewport-gridlines.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html, LitElement, nothing, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { finiteOr, hostAttr, positiveFiniteOr, useStyles } from '@nvidia-elements/core/internal';\nimport styles from './viewport-gridlines.css?inline';\nimport {\n createGridlineCoverage,\n gridlineCoverageNeedsUpdate,\n selectGridlineInterval\n} from './viewport-gridlines.utils.js';\nimport { Viewport } from './viewport.js';\nimport type { ViewportRect } from './viewport.types.js';\n\nconst DEFAULT_STEP = 10;\nconst DEFAULT_TARGET_SPACING = 64;\n\ninterface GridlineProjection {\n readonly coverage: ViewportRect;\n readonly interval: number;\n}\n\ninterface ProjectionSyncOptions {\n readonly forceCoverage?: boolean;\n readonly resetInterval?: boolean;\n}\n\n/**\n * @element nve-viewport-gridlines\n * @description Renders origin-stable, zoom-adaptive gridlines behind viewport content.\n * @documentation https://nvidia.github.io/elements/docs/elements/viewport/\n * @since 0.0.0\n * @entrypoint \\@nvidia-elements/core/viewport\n * @cssprop --color - Sets the gridline stroke color.\n * @cssprop --line-width - Sets the approximate stroke width in CSS pixels.\n */\nexport class ViewportGridlines extends LitElement {\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-viewport-gridlines',\n version: '0.0.0'\n };\n\n /** @private */\n @hostAttr() slot = 'background';\n\n /** @private */\n @hostAttr({ attribute: 'aria-hidden' }) protected accessibilityHidden = 'true';\n\n #step = DEFAULT_STEP;\n #originX = 0;\n #originY = 0;\n #targetSpacing = DEFAULT_TARGET_SPACING;\n #viewport?: Viewport;\n #resizeObserver?: ResizeObserver;\n #projection?: GridlineProjection;\n\n /** Smallest gridline interval in content-space units. */\n @property({ type: Number, reflect: true })\n get step(): number {\n return this.#step;\n }\n\n set step(value: number) {\n const next = positiveFiniteOr(value, DEFAULT_STEP);\n if (next === this.#step) return;\n const previous = this.#step;\n this.#step = next;\n this.requestUpdate('step', previous);\n }\n\n /** Content-space x coordinate of the grid origin. */\n @property({ type: Number, attribute: 'origin-x', reflect: true })\n get originX(): number {\n return this.#originX;\n }\n\n set originX(value: number) {\n const next = finiteOr(value, 0);\n if (next === this.#originX) return;\n const previous = this.#originX;\n this.#originX = next;\n this.requestUpdate('originX', previous);\n }\n\n /** Content-space y coordinate of the grid origin. */\n @property({ type: Number, attribute: 'origin-y', reflect: true })\n get originY(): number {\n return this.#originY;\n }\n\n set originY(value: number) {\n const next = finiteOr(value, 0);\n if (next === this.#originY) return;\n const previous = this.#originY;\n this.#originY = next;\n this.requestUpdate('originY', previous);\n }\n\n /** Target on-screen separation used to choose the adaptive gridline interval, in CSS pixels. */\n @property({ type: Number, attribute: 'target-spacing', reflect: true })\n get targetSpacing(): number {\n return this.#targetSpacing;\n }\n\n set targetSpacing(value: number) {\n const next = positiveFiniteOr(value, DEFAULT_TARGET_SPACING);\n if (next === this.#targetSpacing) return;\n const previous = this.#targetSpacing;\n this.#targetSpacing = next;\n this.requestUpdate('targetSpacing', previous);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n const viewport = this.parentElement?.closest(Viewport.metadata.tag);\n if (!(viewport instanceof Viewport) || viewport !== this.parentElement) return;\n this.#viewport = viewport;\n this.style.setProperty('--_scale', `${viewport.scale}`);\n this.#viewport.addEventListener('viewportchange', this.#handleViewportChange);\n if (typeof ResizeObserver !== 'undefined') {\n this.#resizeObserver = new ResizeObserver(this.#handleViewportResize);\n this.#resizeObserver.observe(viewport);\n }\n this.#updateProjection({ forceCoverage: true, resetInterval: true });\n }\n\n disconnectedCallback(): void {\n if (this.#viewport) {\n this.#viewport.removeEventListener('viewportchange', this.#handleViewportChange);\n }\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n this.#viewport = undefined;\n this.#projection = undefined;\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: PropertyValues<this>): void {\n super.willUpdate(changed);\n if (changed.has('step') || changed.has('targetSpacing')) {\n this.#updateProjection({ forceCoverage: true, resetInterval: true });\n }\n }\n\n render() {\n const projection = this.#projection;\n if (!projection) return nothing;\n const { coverage, interval } = projection;\n return html`\n <svg\n internal-host\n aria-hidden=\"true\"\n focusable=\"false\"\n preserveAspectRatio=\"none\"\n style=${styleMap(coverageStyles(coverage))}\n viewBox=\"${coverage.x} ${coverage.y} ${coverage.width} ${coverage.height}\"\n >\n <defs>\n <pattern\n data-gridline-pattern\n id=\"gridlines\"\n x=${this.#originX}\n y=${this.#originY}\n width=${interval}\n height=${interval}\n patternUnits=\"userSpaceOnUse\"\n >\n <path d=\"M ${interval} 0 H 0 V ${interval}\"></path>\n </pattern>\n </defs>\n <rect\n x=${coverage.x}\n y=${coverage.y}\n width=${coverage.width}\n height=${coverage.height}\n fill=\"url(#gridlines)\"\n ></rect>\n </svg>\n `;\n }\n\n #handleViewportChange = (): void => {\n const viewport = this.#viewport;\n if (!viewport) return;\n this.style.setProperty('--_scale', `${viewport.scale}`);\n this.#requestProjectionUpdate();\n };\n\n #handleViewportResize = (): void => {\n this.#requestProjectionUpdate({ forceCoverage: true });\n };\n\n #requestProjectionUpdate(options: ProjectionSyncOptions = {}): void {\n if (this.#updateProjection(options)) this.requestUpdate();\n }\n\n #updateProjection(options: ProjectionSyncOptions = {}): boolean {\n const viewport = this.#viewport;\n if (!viewport) return false;\n const visible = viewport.getVisibleRect();\n if (visible.width <= 0 || visible.height <= 0) return false;\n const interval = selectGridlineInterval({\n current: options.resetInterval ? undefined : this.#projection?.interval,\n scale: viewport.scale,\n step: this.#step,\n targetSpacing: this.#targetSpacing\n });\n const projection = nextProjection({\n forceCoverage: options.forceCoverage === true,\n interval,\n previous: this.#projection,\n visible\n });\n if (!projection) return false;\n this.#projection = projection;\n return true;\n }\n}\n\nfunction nextProjection({\n forceCoverage,\n interval,\n previous,\n visible\n}: {\n forceCoverage: boolean;\n interval: number;\n previous?: GridlineProjection;\n visible: ViewportRect;\n}): GridlineProjection | undefined {\n const coverageChanged = forceCoverage || gridlineCoverageNeedsUpdate(previous?.coverage, visible);\n const intervalChanged = interval !== previous?.interval;\n if (!coverageChanged && !intervalChanged) return undefined;\n const coverage = coverageChanged || !previous ? createGridlineCoverage(visible) : previous.coverage;\n return { coverage, interval };\n}\n\nfunction coverageStyles(coverage: ViewportRect): Record<string, string> {\n return {\n height: `${coverage.height}px`,\n left: `${coverage.x}px`,\n top: `${coverage.y}px`,\n width: `${coverage.width}px`\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"viewport-gridlines2.js","names":[],"sources":["../../src/viewport/viewport-gridlines.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html, LitElement, nothing, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { finiteOr, hostAttr, positiveFiniteOr, useStyles } from '@nvidia-elements/core/internal';\nimport styles from './viewport-gridlines.css?inline';\nimport {\n createGridlineCoverage,\n gridlineCoverageNeedsUpdate,\n selectGridlineInterval\n} from './viewport-gridlines.utils.js';\nimport { Viewport } from './viewport.js';\nimport type { ViewportRect } from './viewport.types.js';\n\nconst DEFAULT_STEP = 10;\nconst DEFAULT_TARGET_SPACING = 64;\n\ninterface GridlineProjection {\n readonly coverage: ViewportRect;\n readonly interval: number;\n}\n\ninterface ProjectionSyncOptions {\n readonly forceCoverage?: boolean;\n readonly resetInterval?: boolean;\n}\n\n/**\n * @element nve-viewport-gridlines\n * @description Renders origin-stable, zoom-adaptive gridlines behind viewport content.\n * @documentation https://nvidia.github.io/elements/docs/elements/viewport/\n * @since 0.0.0\n * @entrypoint \\@nvidia-elements/core/viewport\n * @cssprop --color - Sets the gridline stroke color.\n * @cssprop --line-width - Sets the approximate stroke width in CSS pixels.\n */\nexport class ViewportGridlines extends LitElement {\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-viewport-gridlines',\n version: '0.0.0'\n };\n\n /** @private */\n @hostAttr() slot = 'background';\n\n /** @private */\n @hostAttr({ attribute: 'aria-hidden' }) protected accessibilityHidden = 'true';\n\n #step = DEFAULT_STEP;\n #originX = 0;\n #originY = 0;\n #targetSpacing = DEFAULT_TARGET_SPACING;\n #viewport?: Viewport;\n #resizeObserver?: ResizeObserver;\n #projection?: GridlineProjection;\n\n /** Smallest gridline interval in content-space units. */\n @property({ type: Number, reflect: true })\n get step(): number {\n return this.#step;\n }\n\n set step(value: number) {\n const next = positiveFiniteOr(value, DEFAULT_STEP);\n if (next === this.#step) return;\n const previous = this.#step;\n this.#step = next;\n this.requestUpdate('step', previous);\n }\n\n /** Content-space x coordinate of the grid origin. */\n @property({ type: Number, attribute: 'origin-x', reflect: true })\n get originX(): number {\n return this.#originX;\n }\n\n set originX(value: number) {\n const next = finiteOr(value, 0);\n if (next === this.#originX) return;\n const previous = this.#originX;\n this.#originX = next;\n this.requestUpdate('originX', previous);\n }\n\n /** Content-space y coordinate of the grid origin. */\n @property({ type: Number, attribute: 'origin-y', reflect: true })\n get originY(): number {\n return this.#originY;\n }\n\n set originY(value: number) {\n const next = finiteOr(value, 0);\n if (next === this.#originY) return;\n const previous = this.#originY;\n this.#originY = next;\n this.requestUpdate('originY', previous);\n }\n\n /** Target on-screen separation used to choose the adaptive gridline interval, in CSS pixels. */\n @property({ type: Number, attribute: 'target-spacing', reflect: true })\n get targetSpacing(): number {\n return this.#targetSpacing;\n }\n\n set targetSpacing(value: number) {\n const next = positiveFiniteOr(value, DEFAULT_TARGET_SPACING);\n if (next === this.#targetSpacing) return;\n const previous = this.#targetSpacing;\n this.#targetSpacing = next;\n this.requestUpdate('targetSpacing', previous);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n const viewport = this.parentElement;\n if (!(viewport instanceof Viewport)) return;\n this.#viewport = viewport;\n this.style.setProperty('--_scale', `${viewport.scale}`);\n this.#viewport.addEventListener('viewportchange', this.#handleViewportChange);\n if (typeof ResizeObserver !== 'undefined') {\n this.#resizeObserver = new ResizeObserver(this.#handleViewportResize);\n this.#resizeObserver.observe(viewport);\n }\n this.#updateProjection({ forceCoverage: true, resetInterval: true });\n }\n\n disconnectedCallback(): void {\n if (this.#viewport) {\n this.#viewport.removeEventListener('viewportchange', this.#handleViewportChange);\n }\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n this.#viewport = undefined;\n this.#projection = undefined;\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: PropertyValues<this>): void {\n super.willUpdate(changed);\n if (changed.has('step') || changed.has('targetSpacing')) {\n this.#updateProjection({ forceCoverage: true, resetInterval: true });\n }\n }\n\n render() {\n const projection = this.#projection;\n if (!projection) return nothing;\n const { coverage, interval } = projection;\n return html`\n <svg\n internal-host\n aria-hidden=\"true\"\n focusable=\"false\"\n preserveAspectRatio=\"none\"\n style=${styleMap(coverageStyles(coverage))}\n viewBox=\"${coverage.x} ${coverage.y} ${coverage.width} ${coverage.height}\"\n >\n <defs>\n <pattern\n data-gridline-pattern\n id=\"gridlines\"\n x=${this.#originX}\n y=${this.#originY}\n width=${interval}\n height=${interval}\n patternUnits=\"userSpaceOnUse\"\n >\n <path d=\"M ${interval} 0 H 0 V ${interval}\"></path>\n </pattern>\n </defs>\n <rect\n x=${coverage.x}\n y=${coverage.y}\n width=${coverage.width}\n height=${coverage.height}\n fill=\"url(#gridlines)\"\n ></rect>\n </svg>\n `;\n }\n\n #handleViewportChange = (): void => {\n const viewport = this.#viewport;\n if (!viewport) return;\n this.style.setProperty('--_scale', `${viewport.scale}`);\n this.#requestProjectionUpdate();\n };\n\n #handleViewportResize = (): void => {\n this.#requestProjectionUpdate({ forceCoverage: true });\n };\n\n #requestProjectionUpdate(options: ProjectionSyncOptions = {}): void {\n if (this.#updateProjection(options)) this.requestUpdate();\n }\n\n #updateProjection(options: ProjectionSyncOptions = {}): boolean {\n const viewport = this.#viewport;\n if (!viewport) return false;\n const visible = viewport.getVisibleRect();\n if (visible.width <= 0 || visible.height <= 0) return false;\n const interval = selectGridlineInterval({\n current: options.resetInterval ? undefined : this.#projection?.interval,\n scale: viewport.scale,\n step: this.#step,\n targetSpacing: this.#targetSpacing\n });\n const projection = nextProjection({\n forceCoverage: options.forceCoverage === true,\n interval,\n previous: this.#projection,\n visible\n });\n if (!projection) return false;\n this.#projection = projection;\n return true;\n }\n}\n\nfunction nextProjection({\n forceCoverage,\n interval,\n previous,\n visible\n}: {\n forceCoverage: boolean;\n interval: number;\n previous?: GridlineProjection;\n visible: ViewportRect;\n}): GridlineProjection | undefined {\n const coverageChanged = forceCoverage || gridlineCoverageNeedsUpdate(previous?.coverage, visible);\n const intervalChanged = interval !== previous?.interval;\n if (!coverageChanged && !intervalChanged) return undefined;\n const coverage = coverageChanged || !previous ? createGridlineCoverage(visible) : previous.coverage;\n return { coverage, interval };\n}\n\nfunction coverageStyles(coverage: ViewportRect): Record<string, string> {\n return {\n height: `${coverage.height}px`,\n left: `${coverage.x}px`,\n top: `${coverage.y}px`,\n width: `${coverage.width}px`\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { LitElement } from 'lit';
2
+ /**
3
+ * @element nve-viewport-minimap
4
+ * @description Provides a simplified overview and direct navigation for its parent viewport.
5
+ * @documentation https://nvidia.github.io/elements/docs/elements/viewport/
6
+ * @since 0.0.0
7
+ * @entrypoint \@nvidia-elements/core/viewport
8
+ * @cssprop --background - Color of the surface behind preview geometry.
9
+ * @cssprop --color - Color of automatically drawn root rectangles.
10
+ * @cssprop --indicator-color - Color of the current visible-region indicator.
11
+ * @cssprop --border-radius - Corner radius of the minimap.
12
+ * @cssprop --recenter-cursor - Cursor for clicking the background to center the viewport.
13
+ * @cssprop --pan-cursor - Cursor over a draggable visible region.
14
+ * @cssprop --panning-cursor - Cursor during a visible-region drag.
15
+ * @slot preview - Optional simplified content drawn in viewport content coordinates. Replaces automatic root rectangles.
16
+ */
17
+ export declare class ViewportMinimap extends LitElement {
18
+ #private;
19
+ static styles: import("lit").CSSResult[];
20
+ static readonly metadata: {
21
+ tag: string;
22
+ version: string;
23
+ };
24
+ /** @private */
25
+ _internals: ElementInternals;
26
+ /** @private */
27
+ slot: string;
28
+ /** @private */
29
+ protected accessibilityHidden: string;
30
+ constructor();
31
+ connectedCallback(): void;
32
+ disconnectedCallback(): void;
33
+ /** Remeasures content bounds after preview or viewport roots move without resizing. */
34
+ refresh(): void;
35
+ render(): import("lit-html").TemplateResult<1>;
36
+ }
@@ -0,0 +1,6 @@
1
+ //#region src/viewport/viewport-minimap.css?inline
2
+ var e = ":host{--background: var(--nve-sys-layer-container-background);--color: var(--nve-sys-text-muted-color);--indicator-color: var(--nve-sys-support-accent-color);--border-radius: var(--nve-ref-border-radius-md);position:absolute;inset-block-end:var(--nve-ref-space-xs);inset-inline-end:var(--nve-ref-space-xs);display:block;box-sizing:border-box;inline-size:clamp(8rem,32%,10rem);max-inline-size:calc(100% - 1rem);aspect-ratio:4 / 3;overflow:hidden;border-radius:var(--border-radius);contain:content;cursor:default;user-select:none}.surface{position:relative;inline-size:100%;block-size:100%}svg{position:absolute;inset:0;display:block;inline-size:100%;block-size:100%;overflow:hidden;border-radius:inherit}.preview{position:absolute;inset:0;transform-origin:0 0;pointer-events:none}.foreground-layer{pointer-events:none}.background{fill:var(--background)}.item{fill:var(--color);pointer-events:none}.visible-region{fill:var(--indicator-color);fill-opacity:.15;stroke:var(--indicator-color);stroke-width:1.5;vector-effect:non-scaling-stroke;pointer-events:all}:host(:state(pan-eligible)) .background{cursor:var(--recenter-cursor, pointer)}:host(:state(pan-eligible)) .visible-region{cursor:var(--pan-cursor, grab)}:host(:state(panning)),:host(:state(panning)) .background,:host(:state(panning)) .visible-region{cursor:var(--panning-cursor, grabbing)}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=viewport-minimap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport-minimap.js","names":[],"sources":["../../src/viewport/viewport-minimap.css?inline"],"sourcesContent":["/* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */\n/* SPDX-License-Identifier: Apache-2.0 */\n:host {\n --background: var(--nve-sys-layer-container-background);\n --color: var(--nve-sys-text-muted-color);\n --indicator-color: var(--nve-sys-support-accent-color);\n --border-radius: var(--nve-ref-border-radius-md);\n\n position: absolute;\n inset-block-end: var(--nve-ref-space-xs);\n inset-inline-end: var(--nve-ref-space-xs);\n display: block;\n box-sizing: border-box;\n inline-size: clamp(8rem, 32%, 10rem);\n max-inline-size: calc(100% - 1rem);\n aspect-ratio: 4 / 3;\n overflow: hidden;\n border-radius: var(--border-radius);\n contain: content;\n cursor: default;\n user-select: none;\n}\n\n.surface {\n position: relative;\n inline-size: 100%;\n block-size: 100%;\n}\n\nsvg {\n position: absolute;\n inset: 0;\n display: block;\n inline-size: 100%;\n block-size: 100%;\n overflow: hidden;\n border-radius: inherit;\n}\n\n.preview {\n position: absolute;\n inset: 0;\n transform-origin: 0 0;\n pointer-events: none;\n}\n\n.foreground-layer {\n pointer-events: none;\n}\n\n.background {\n fill: var(--background);\n}\n\n.item {\n fill: var(--color);\n pointer-events: none;\n}\n\n.visible-region {\n fill: var(--indicator-color);\n fill-opacity: 0.15;\n stroke: var(--indicator-color);\n stroke-width: 1.5;\n vector-effect: non-scaling-stroke;\n pointer-events: all;\n}\n\n:host(:state(pan-eligible)) .background {\n cursor: var(--recenter-cursor, pointer);\n}\n\n:host(:state(pan-eligible)) .visible-region {\n cursor: var(--pan-cursor, grab);\n}\n\n:host(:state(panning)),\n:host(:state(panning)) .background,\n:host(:state(panning)) .visible-region {\n cursor: var(--panning-cursor, grabbing);\n}\n"],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { ViewportPoint, ViewportRect } from './viewport.types.js';
2
+ export interface ViewportMinimapProjection {
3
+ readonly offsetX: number;
4
+ readonly offsetY: number;
5
+ readonly scale: number;
6
+ }
7
+ export declare function hasPositiveFiniteRect(rect: ViewportRect): boolean;
8
+ export declare function createViewportMinimapProjection(content: readonly ViewportRect[], visible: ViewportRect, size: {
9
+ readonly width: number;
10
+ readonly height: number;
11
+ }): ViewportMinimapProjection | undefined;
12
+ export declare function projectViewportMinimapRect(rect: ViewportRect, projection: ViewportMinimapProjection): ViewportRect;
13
+ export declare function unprojectViewportMinimapPoint(point: ViewportPoint, projection: ViewportMinimapProjection): ViewportPoint;
@@ -0,0 +1,49 @@
1
+ //#region src/viewport/viewport-minimap.utils.ts
2
+ var e = .1;
3
+ function t(e) {
4
+ return Number.isFinite(e.x) && Number.isFinite(e.y) && Number.isFinite(e.width) && Number.isFinite(e.height) && e.width > 0 && e.height > 0;
5
+ }
6
+ function n(t, n, r) {
7
+ if (r.width <= 0 || r.height <= 0 || n.width <= 0 || n.height <= 0) return;
8
+ let i = a([n, ...t]);
9
+ if (!i) return;
10
+ let o = Math.max(i.width * e, 2 ** -52), s = Math.max(i.height * e, 2 ** -52), c = {
11
+ x: i.x - o,
12
+ y: i.y - s,
13
+ width: i.width + o * 2,
14
+ height: i.height + s * 2
15
+ }, l = Math.min(r.width / c.width, r.height / c.height);
16
+ if (!(!Number.isFinite(l) || l <= 0)) return {
17
+ offsetX: (r.width - c.width * l) / 2 - c.x * l,
18
+ offsetY: (r.height - c.height * l) / 2 - c.y * l,
19
+ scale: l
20
+ };
21
+ }
22
+ function r(e, t) {
23
+ return {
24
+ x: e.x * t.scale + t.offsetX,
25
+ y: e.y * t.scale + t.offsetY,
26
+ width: e.width * t.scale,
27
+ height: e.height * t.scale
28
+ };
29
+ }
30
+ function i(e, t) {
31
+ return {
32
+ x: (e.x - t.offsetX) / t.scale,
33
+ y: (e.y - t.offsetY) / t.scale
34
+ };
35
+ }
36
+ function a(e) {
37
+ let n = Infinity, r = Infinity, i = -Infinity, a = -Infinity;
38
+ for (let o of e) t(o) && (n = Math.min(n, o.x), r = Math.min(r, o.y), i = Math.max(i, o.x + o.width), a = Math.max(a, o.y + o.height));
39
+ if (!(!Number.isFinite(n) || !Number.isFinite(r) || i <= n || a <= r)) return {
40
+ x: n,
41
+ y: r,
42
+ width: i - n,
43
+ height: a - r
44
+ };
45
+ }
46
+ //#endregion
47
+ export { n as createViewportMinimapProjection, t as hasPositiveFiniteRect, r as projectViewportMinimapRect, i as unprojectViewportMinimapPoint };
48
+
49
+ //# sourceMappingURL=viewport-minimap.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport-minimap.utils.js","names":[],"sources":["../../src/viewport/viewport-minimap.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ViewportPoint, ViewportRect } from './viewport.types.js';\n\nconst PROJECTION_PADDING = 0.1;\n\nexport interface ViewportMinimapProjection {\n readonly offsetX: number;\n readonly offsetY: number;\n readonly scale: number;\n}\n\nexport function hasPositiveFiniteRect(rect: ViewportRect): boolean {\n return (\n Number.isFinite(rect.x) &&\n Number.isFinite(rect.y) &&\n Number.isFinite(rect.width) &&\n Number.isFinite(rect.height) &&\n rect.width > 0 &&\n rect.height > 0\n );\n}\n\nexport function createViewportMinimapProjection(\n content: readonly ViewportRect[],\n visible: ViewportRect,\n size: { readonly width: number; readonly height: number }\n): ViewportMinimapProjection | undefined {\n if (size.width <= 0 || size.height <= 0 || visible.width <= 0 || visible.height <= 0) return undefined;\n const extent = unionRects([visible, ...content]);\n if (!extent) return undefined;\n const paddingX = Math.max(extent.width * PROJECTION_PADDING, Number.EPSILON);\n const paddingY = Math.max(extent.height * PROJECTION_PADDING, Number.EPSILON);\n const coverage = {\n x: extent.x - paddingX,\n y: extent.y - paddingY,\n width: extent.width + paddingX * 2,\n height: extent.height + paddingY * 2\n };\n const scale = Math.min(size.width / coverage.width, size.height / coverage.height);\n if (!Number.isFinite(scale) || scale <= 0) return undefined;\n return {\n offsetX: (size.width - coverage.width * scale) / 2 - coverage.x * scale,\n offsetY: (size.height - coverage.height * scale) / 2 - coverage.y * scale,\n scale\n };\n}\n\nexport function projectViewportMinimapRect(rect: ViewportRect, projection: ViewportMinimapProjection): ViewportRect {\n return {\n x: rect.x * projection.scale + projection.offsetX,\n y: rect.y * projection.scale + projection.offsetY,\n width: rect.width * projection.scale,\n height: rect.height * projection.scale\n };\n}\n\nexport function unprojectViewportMinimapPoint(\n point: ViewportPoint,\n projection: ViewportMinimapProjection\n): ViewportPoint {\n return {\n x: (point.x - projection.offsetX) / projection.scale,\n y: (point.y - projection.offsetY) / projection.scale\n };\n}\n\nfunction unionRects(rects: readonly ViewportRect[]): ViewportRect | undefined {\n let left = Number.POSITIVE_INFINITY;\n let top = Number.POSITIVE_INFINITY;\n let right = Number.NEGATIVE_INFINITY;\n let bottom = Number.NEGATIVE_INFINITY;\n for (const rect of rects) {\n if (!hasPositiveFiniteRect(rect)) continue;\n left = Math.min(left, rect.x);\n top = Math.min(top, rect.y);\n right = Math.max(right, rect.x + rect.width);\n bottom = Math.max(bottom, rect.y + rect.height);\n }\n if (!Number.isFinite(left) || !Number.isFinite(top) || right <= left || bottom <= top) return undefined;\n return { x: left, y: top, width: right - left, height: bottom - top };\n}\n"],"mappings":";AAKA,IAAM,IAAqB;AAQ3B,SAAgB,EAAsB,GAA6B;CACjE,OACE,OAAO,SAAS,EAAK,CAAC,KACtB,OAAO,SAAS,EAAK,CAAC,KACtB,OAAO,SAAS,EAAK,KAAK,KAC1B,OAAO,SAAS,EAAK,MAAM,KAC3B,EAAK,QAAQ,KACb,EAAK,SAAS;AAElB;AAEA,SAAgB,EACd,GACA,GACA,GACuC;CACvC,IAAI,EAAK,SAAS,KAAK,EAAK,UAAU,KAAK,EAAQ,SAAS,KAAK,EAAQ,UAAU,GAAG;CACtF,IAAM,IAAS,EAAW,CAAC,GAAS,GAAG,CAAO,CAAC;CAC/C,IAAI,CAAC,GAAQ;CACb,IAAM,IAAW,KAAK,IAAI,EAAO,QAAQ,WAAkC,GACrE,IAAW,KAAK,IAAI,EAAO,SAAS,WAAkC,GACtE,IAAW;EACf,GAAG,EAAO,IAAI;EACd,GAAG,EAAO,IAAI;EACd,OAAO,EAAO,QAAQ,IAAW;EACjC,QAAQ,EAAO,SAAS,IAAW;CACrC,GACM,IAAQ,KAAK,IAAI,EAAK,QAAQ,EAAS,OAAO,EAAK,SAAS,EAAS,MAAM;CAC7E,OAAC,OAAO,SAAS,CAAK,KAAK,KAAS,IACxC,OAAO;EACL,UAAU,EAAK,QAAQ,EAAS,QAAQ,KAAS,IAAI,EAAS,IAAI;EAClE,UAAU,EAAK,SAAS,EAAS,SAAS,KAAS,IAAI,EAAS,IAAI;EACpE;CACF;AACF;AAEA,SAAgB,EAA2B,GAAoB,GAAqD;CAClH,OAAO;EACL,GAAG,EAAK,IAAI,EAAW,QAAQ,EAAW;EAC1C,GAAG,EAAK,IAAI,EAAW,QAAQ,EAAW;EAC1C,OAAO,EAAK,QAAQ,EAAW;EAC/B,QAAQ,EAAK,SAAS,EAAW;CACnC;AACF;AAEA,SAAgB,EACd,GACA,GACe;CACf,OAAO;EACL,IAAI,EAAM,IAAI,EAAW,WAAW,EAAW;EAC/C,IAAI,EAAM,IAAI,EAAW,WAAW,EAAW;CACjD;AACF;AAEA,SAAS,EAAW,GAA0D;CAC5E,IAAI,IAAO,UACP,IAAM,UACN,IAAQ,WACR,IAAS;CACb,KAAK,IAAM,KAAQ,GACZ,EAAsB,CAAI,MAC/B,IAAO,KAAK,IAAI,GAAM,EAAK,CAAC,GAC5B,IAAM,KAAK,IAAI,GAAK,EAAK,CAAC,GAC1B,IAAQ,KAAK,IAAI,GAAO,EAAK,IAAI,EAAK,KAAK,GAC3C,IAAS,KAAK,IAAI,GAAQ,EAAK,IAAI,EAAK,MAAM;CAE5C,OAAC,OAAO,SAAS,CAAI,KAAK,CAAC,OAAO,SAAS,CAAG,KAAK,KAAS,KAAQ,KAAU,IAClF,OAAO;EAAE,GAAG;EAAM,GAAG;EAAK,OAAO,IAAQ;EAAM,QAAQ,IAAS;CAAI;AACtE"}