@remix-run/ui 0.0.0 → 0.1.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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -2
  3. package/dist/animation/animate-layout-mixin.d.ts +12 -0
  4. package/dist/animation/animate-layout-mixin.js +214 -0
  5. package/dist/animation/animate-layout-mixin.js.map +1 -0
  6. package/dist/animation/animate-mixins.d.ts +29 -0
  7. package/dist/animation/animate-mixins.js +235 -0
  8. package/dist/animation/animate-mixins.js.map +1 -0
  9. package/dist/animation/index.d.ts +6 -0
  10. package/dist/animation/index.js +5 -0
  11. package/dist/animation/index.js.map +1 -0
  12. package/dist/animation/spring.d.ts +75 -0
  13. package/dist/animation/spring.js +183 -0
  14. package/dist/animation/spring.js.map +1 -0
  15. package/dist/animation/tween.d.ts +70 -0
  16. package/dist/animation/tween.js +93 -0
  17. package/dist/animation/tween.js.map +1 -0
  18. package/dist/components/accordion/accordion.d.ts +92 -0
  19. package/dist/components/accordion/accordion.js +337 -0
  20. package/dist/components/accordion/accordion.js.map +1 -0
  21. package/dist/components/anchor/anchor.d.ts +13 -0
  22. package/dist/components/anchor/anchor.js +558 -0
  23. package/dist/components/anchor/anchor.js.map +1 -0
  24. package/dist/components/breadcrumbs/breadcrumbs.d.ts +11 -0
  25. package/dist/components/breadcrumbs/breadcrumbs.js +78 -0
  26. package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -0
  27. package/dist/components/button/button.d.ts +23 -0
  28. package/dist/components/button/button.js +147 -0
  29. package/dist/components/button/button.js.map +1 -0
  30. package/dist/components/combobox/combobox.d.ts +101 -0
  31. package/dist/components/combobox/combobox.js +708 -0
  32. package/dist/components/combobox/combobox.js.map +1 -0
  33. package/dist/components/glyph/glyph.d.ts +14 -0
  34. package/dist/components/glyph/glyph.js +65 -0
  35. package/dist/components/glyph/glyph.js.map +1 -0
  36. package/dist/components/listbox/listbox.d.ts +67 -0
  37. package/dist/components/listbox/listbox.js +340 -0
  38. package/dist/components/listbox/listbox.js.map +1 -0
  39. package/dist/components/menu/hover-aim.d.ts +5 -0
  40. package/dist/components/menu/hover-aim.js +308 -0
  41. package/dist/components/menu/hover-aim.js.map +1 -0
  42. package/dist/components/menu/menu.d.ts +164 -0
  43. package/dist/components/menu/menu.js +1106 -0
  44. package/dist/components/menu/menu.js.map +1 -0
  45. package/dist/components/popover/popover.d.ts +35 -0
  46. package/dist/components/popover/popover.js +138 -0
  47. package/dist/components/popover/popover.js.map +1 -0
  48. package/dist/components/select/select.d.ts +67 -0
  49. package/dist/components/select/select.js +397 -0
  50. package/dist/components/select/select.js.map +1 -0
  51. package/dist/components/separator/separator.d.ts +2 -0
  52. package/dist/components/separator/separator.js +15 -0
  53. package/dist/components/separator/separator.js.map +1 -0
  54. package/dist/components/tabs/tabs.d.ts +78 -0
  55. package/dist/components/tabs/tabs.js +341 -0
  56. package/dist/components/tabs/tabs.js.map +1 -0
  57. package/dist/index.d.ts +28 -0
  58. package/dist/index.js +21 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/interactions/keydown/keydown.d.ts +1 -0
  61. package/dist/interactions/keydown/keydown.js +8 -0
  62. package/dist/interactions/keydown/keydown.js.map +1 -0
  63. package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -0
  64. package/dist/interactions/outside-click/outside-click-mixin.js +29 -0
  65. package/dist/interactions/outside-click/outside-click-mixin.js.map +1 -0
  66. package/dist/interactions/typeahead/typeahead-mixin.d.ts +8 -0
  67. package/dist/interactions/typeahead/typeahead-mixin.js +59 -0
  68. package/dist/interactions/typeahead/typeahead-mixin.js.map +1 -0
  69. package/dist/jsx-runtime.d.ts +2 -0
  70. package/dist/jsx-runtime.js +3 -0
  71. package/dist/jsx-runtime.js.map +1 -0
  72. package/dist/runtime/client-entries.d.ts +91 -0
  73. package/dist/runtime/client-entries.js +40 -0
  74. package/dist/runtime/client-entries.js.map +1 -0
  75. package/dist/runtime/component.d.ts +223 -0
  76. package/dist/runtime/component.js +152 -0
  77. package/dist/runtime/component.js.map +1 -0
  78. package/dist/runtime/create-element.d.ts +10 -0
  79. package/dist/runtime/create-element.js +29 -0
  80. package/dist/runtime/create-element.js.map +1 -0
  81. package/dist/runtime/diff-dom.d.ts +2 -0
  82. package/dist/runtime/diff-dom.js +364 -0
  83. package/dist/runtime/diff-dom.js.map +1 -0
  84. package/dist/runtime/diff-props.d.ts +9 -0
  85. package/dist/runtime/diff-props.js +195 -0
  86. package/dist/runtime/diff-props.js.map +1 -0
  87. package/dist/runtime/document-state.d.ts +11 -0
  88. package/dist/runtime/document-state.js +106 -0
  89. package/dist/runtime/document-state.js.map +1 -0
  90. package/dist/runtime/dom.d.ts +3189 -0
  91. package/dist/runtime/dom.js +2 -0
  92. package/dist/runtime/dom.js.map +1 -0
  93. package/dist/runtime/error-event.d.ts +20 -0
  94. package/dist/runtime/error-event.js +19 -0
  95. package/dist/runtime/error-event.js.map +1 -0
  96. package/dist/runtime/event-listeners.d.ts +50 -0
  97. package/dist/runtime/event-listeners.js +31 -0
  98. package/dist/runtime/event-listeners.js.map +1 -0
  99. package/dist/runtime/frame.d.ts +119 -0
  100. package/dist/runtime/frame.js +915 -0
  101. package/dist/runtime/frame.js.map +1 -0
  102. package/dist/runtime/invariant.d.ts +23 -0
  103. package/dist/runtime/invariant.js +33 -0
  104. package/dist/runtime/invariant.js.map +1 -0
  105. package/dist/runtime/jsx.d.ts +320 -0
  106. package/dist/runtime/jsx.js +31 -0
  107. package/dist/runtime/jsx.js.map +1 -0
  108. package/dist/runtime/mixins/attrs-mixin.d.ts +9 -0
  109. package/dist/runtime/mixins/attrs-mixin.js +23 -0
  110. package/dist/runtime/mixins/attrs-mixin.js.map +1 -0
  111. package/dist/runtime/mixins/link-mixin.d.ts +17 -0
  112. package/dist/runtime/mixins/link-mixin.js +101 -0
  113. package/dist/runtime/mixins/link-mixin.js.map +1 -0
  114. package/dist/runtime/mixins/mixin.d.ts +145 -0
  115. package/dist/runtime/mixins/mixin.js +570 -0
  116. package/dist/runtime/mixins/mixin.js.map +1 -0
  117. package/dist/runtime/mixins/on-mixin.d.ts +16 -0
  118. package/dist/runtime/mixins/on-mixin.js +49 -0
  119. package/dist/runtime/mixins/on-mixin.js.map +1 -0
  120. package/dist/runtime/mixins/ref-mixin.d.ts +9 -0
  121. package/dist/runtime/mixins/ref-mixin.js +21 -0
  122. package/dist/runtime/mixins/ref-mixin.js.map +1 -0
  123. package/dist/runtime/navigation.d.ts +22 -0
  124. package/dist/runtime/navigation.js +102 -0
  125. package/dist/runtime/navigation.js.map +1 -0
  126. package/dist/runtime/reconcile.d.ts +11 -0
  127. package/dist/runtime/reconcile.js +1240 -0
  128. package/dist/runtime/reconcile.js.map +1 -0
  129. package/dist/runtime/render.d.ts +54 -0
  130. package/dist/runtime/render.js +50 -0
  131. package/dist/runtime/render.js.map +1 -0
  132. package/dist/runtime/run.d.ts +45 -0
  133. package/dist/runtime/run.js +68 -0
  134. package/dist/runtime/run.js.map +1 -0
  135. package/dist/runtime/scheduler.d.ts +30 -0
  136. package/dist/runtime/scheduler.js +185 -0
  137. package/dist/runtime/scheduler.js.map +1 -0
  138. package/dist/runtime/svg-attributes.d.ts +5 -0
  139. package/dist/runtime/svg-attributes.js +124 -0
  140. package/dist/runtime/svg-attributes.js.map +1 -0
  141. package/dist/runtime/to-vnode.d.ts +3 -0
  142. package/dist/runtime/to-vnode.js +43 -0
  143. package/dist/runtime/to-vnode.js.map +1 -0
  144. package/dist/runtime/typed-event-target.d.ts +50 -0
  145. package/dist/runtime/typed-event-target.js +6 -0
  146. package/dist/runtime/typed-event-target.js.map +1 -0
  147. package/dist/runtime/vdom.d.ts +55 -0
  148. package/dist/runtime/vdom.js +198 -0
  149. package/dist/runtime/vdom.js.map +1 -0
  150. package/dist/runtime/vnode.d.ts +79 -0
  151. package/dist/runtime/vnode.js +38 -0
  152. package/dist/runtime/vnode.js.map +1 -0
  153. package/dist/server/stream.d.ts +57 -0
  154. package/dist/server/stream.js +1007 -0
  155. package/dist/server/stream.js.map +1 -0
  156. package/dist/style/css-mixin.d.ts +8 -0
  157. package/dist/style/css-mixin.js +54 -0
  158. package/dist/style/css-mixin.js.map +1 -0
  159. package/dist/style/index.d.ts +5 -0
  160. package/dist/style/index.js +4 -0
  161. package/dist/style/index.js.map +1 -0
  162. package/dist/style/style.d.ts +24 -0
  163. package/dist/style/style.js +269 -0
  164. package/dist/style/style.js.map +1 -0
  165. package/dist/style/stylesheet.d.ts +11 -0
  166. package/dist/style/stylesheet.js +174 -0
  167. package/dist/style/stylesheet.js.map +1 -0
  168. package/dist/test.d.ts +2 -0
  169. package/dist/test.js +2 -0
  170. package/dist/test.js.map +1 -0
  171. package/dist/theme/contract.d.ts +259 -0
  172. package/dist/theme/contract.js +131 -0
  173. package/dist/theme/contract.js.map +1 -0
  174. package/dist/theme/glyph-contract.d.ts +13 -0
  175. package/dist/theme/glyph-contract.js +34 -0
  176. package/dist/theme/glyph-contract.js.map +1 -0
  177. package/dist/theme/presets/rmx-01/glyphs.d.ts +2 -0
  178. package/dist/theme/presets/rmx-01/glyphs.js +252 -0
  179. package/dist/theme/presets/rmx-01/glyphs.js.map +1 -0
  180. package/dist/theme/presets/rmx-01/index.d.ts +2 -0
  181. package/dist/theme/presets/rmx-01/index.js +119 -0
  182. package/dist/theme/presets/rmx-01/index.js.map +1 -0
  183. package/dist/theme/runtime.d.ts +2 -0
  184. package/dist/theme/runtime.js +81 -0
  185. package/dist/theme/runtime.js.map +1 -0
  186. package/dist/theme/theme.d.ts +6 -0
  187. package/dist/theme/theme.js +5 -0
  188. package/dist/theme/theme.js.map +1 -0
  189. package/dist/utils/flash-attribute.d.ts +1 -0
  190. package/dist/utils/flash-attribute.js +11 -0
  191. package/dist/utils/flash-attribute.js.map +1 -0
  192. package/dist/utils/scroll-lock.d.ts +3 -0
  193. package/dist/utils/scroll-lock.js +69 -0
  194. package/dist/utils/scroll-lock.js.map +1 -0
  195. package/dist/utils/wait-for-css-transition.d.ts +1 -0
  196. package/dist/utils/wait-for-css-transition.js +58 -0
  197. package/dist/utils/wait-for-css-transition.js.map +1 -0
  198. package/dist/utils/wait.d.ts +1 -0
  199. package/dist/utils/wait.js +6 -0
  200. package/dist/utils/wait.js.map +1 -0
  201. package/package.json +125 -5
  202. package/src/animation/animate-layout-mixin.ts +266 -0
  203. package/src/animation/animate-mixins.ts +292 -0
  204. package/src/animation/index.ts +6 -0
  205. package/src/animation/spring.ts +299 -0
  206. package/src/animation/tween.ts +134 -0
  207. package/src/components/accordion/accordion.tsx +565 -0
  208. package/src/components/anchor/anchor.ts +904 -0
  209. package/src/components/breadcrumbs/breadcrumbs.tsx +124 -0
  210. package/src/components/button/README.md +44 -0
  211. package/src/components/button/button.tsx +188 -0
  212. package/src/components/combobox/README.md +145 -0
  213. package/src/components/combobox/combobox.tsx +1014 -0
  214. package/src/components/glyph/glyph.tsx +110 -0
  215. package/src/components/listbox/listbox.ts +447 -0
  216. package/src/components/menu/hover-aim.ts +428 -0
  217. package/src/components/menu/menu.tsx +1547 -0
  218. package/src/components/popover/README.md +122 -0
  219. package/src/components/popover/popover.ts +201 -0
  220. package/src/components/select/select.tsx +585 -0
  221. package/src/components/separator/separator.ts +19 -0
  222. package/src/components/tabs/README.md +105 -0
  223. package/src/components/tabs/tabs.tsx +499 -0
  224. package/src/index.ts +72 -0
  225. package/src/interactions/keydown/keydown.ts +14 -0
  226. package/src/interactions/outside-click/outside-click-mixin.ts +55 -0
  227. package/src/interactions/typeahead/typeahead-mixin.ts +89 -0
  228. package/src/jsx-runtime.ts +2 -0
  229. package/src/runtime/client-entries.ts +137 -0
  230. package/src/runtime/component.ts +402 -0
  231. package/src/runtime/create-element.ts +38 -0
  232. package/src/runtime/diff-dom.ts +404 -0
  233. package/src/runtime/diff-props.ts +209 -0
  234. package/src/runtime/document-state.ts +130 -0
  235. package/src/runtime/dom.ts +3971 -0
  236. package/src/runtime/error-event.ts +26 -0
  237. package/src/runtime/event-listeners.ts +171 -0
  238. package/src/runtime/frame.ts +1211 -0
  239. package/src/runtime/invariant.ts +31 -0
  240. package/src/runtime/jsx.ts +398 -0
  241. package/src/runtime/mixins/attrs-mixin.ts +35 -0
  242. package/src/runtime/mixins/link-mixin.ts +131 -0
  243. package/src/runtime/mixins/mixin.ts +908 -0
  244. package/src/runtime/mixins/on-mixin.ts +89 -0
  245. package/src/runtime/mixins/ref-mixin.ts +32 -0
  246. package/src/runtime/navigation.ts +136 -0
  247. package/src/runtime/reconcile.ts +1722 -0
  248. package/src/runtime/render.ts +101 -0
  249. package/src/runtime/run.ts +100 -0
  250. package/src/runtime/scheduler.ts +262 -0
  251. package/src/runtime/svg-attributes.ts +133 -0
  252. package/src/runtime/to-vnode.ts +50 -0
  253. package/src/runtime/typed-event-target.ts +67 -0
  254. package/src/runtime/vdom.ts +295 -0
  255. package/src/runtime/vnode.ts +137 -0
  256. package/src/server/stream.ts +1342 -0
  257. package/src/style/css-mixin.ts +82 -0
  258. package/src/style/index.ts +10 -0
  259. package/src/style/style.ts +312 -0
  260. package/src/style/stylesheet.ts +209 -0
  261. package/src/test/setup.ts +7 -0
  262. package/src/test/utils.ts +45 -0
  263. package/src/test.ts +2 -0
  264. package/src/theme/contract.ts +183 -0
  265. package/src/theme/glyph-contract.ts +57 -0
  266. package/src/theme/presets/rmx-01/glyphs.tsx +308 -0
  267. package/src/theme/presets/rmx-01/index.ts +121 -0
  268. package/src/theme/runtime.ts +116 -0
  269. package/src/theme/theme.ts +15 -0
  270. package/src/utils/flash-attribute.ts +11 -0
  271. package/src/utils/scroll-lock.ts +97 -0
  272. package/src/utils/wait-for-css-transition.ts +66 -0
  273. package/src/utils/wait.ts +5 -0
@@ -0,0 +1,89 @@
1
+ import { createMixin } from './mixin.ts'
2
+ import type { ElementProps } from '../jsx.ts'
3
+ import type { MixinDescriptor } from './mixin.ts'
4
+ import type {
5
+ EventType as AddEventType,
6
+ ListenerFor as AddEventListenerFor,
7
+ } from '../event-listeners.ts'
8
+
9
+ export type { Dispatched } from '../event-listeners.ts'
10
+
11
+ type SignaledListener<event extends Event> = (
12
+ event: event,
13
+ signal: AbortSignal,
14
+ ) => void | Promise<void>
15
+
16
+ type EventType<target extends Element> = Extract<AddEventType<target>, string>
17
+ type ListenerFor<target extends Element, type extends EventType<target>> = SignaledListener<
18
+ Parameters<AddEventListenerFor<target, type>>[0]
19
+ >
20
+
21
+ const onMixin = createMixin<
22
+ Element,
23
+ [type: string, handler: SignaledListener<Event>, captureBoolean?: boolean],
24
+ ElementProps
25
+ >((handle) => {
26
+ let currentHandler: SignaledListener<Event> = () => {}
27
+ let currentType = ''
28
+ let currentCapture = false
29
+ let currentNode: Element | null = null
30
+ let reentry: AbortController | null = null
31
+
32
+ let stableHandler = (event: Event) => {
33
+ reentry?.abort(new DOMException('', 'EventReentry'))
34
+ reentry = new AbortController()
35
+ void currentHandler(event, reentry.signal)
36
+ }
37
+
38
+ handle.addEventListener('insert', (event) => {
39
+ currentNode = event.node
40
+ currentNode.addEventListener(currentType, stableHandler, currentCapture)
41
+ })
42
+
43
+ handle.addEventListener('remove', () => {
44
+ currentNode?.removeEventListener(currentType, stableHandler, currentCapture)
45
+ currentNode = null
46
+ reentry?.abort(new DOMException('', 'AbortError'))
47
+ })
48
+
49
+ return (type, handler, captureBoolean = false) => {
50
+ let previousType = currentType
51
+ let previousCapture = currentCapture
52
+ let needsRebind = currentType !== type || currentCapture !== captureBoolean
53
+ currentType = type
54
+ currentHandler = handler
55
+ currentCapture = captureBoolean
56
+
57
+ if (needsRebind && currentNode) {
58
+ currentNode.removeEventListener(previousType, stableHandler, previousCapture)
59
+ currentNode.addEventListener(type, stableHandler, captureBoolean)
60
+ }
61
+
62
+ return handle.element
63
+ }
64
+ })
65
+
66
+ /**
67
+ * Attaches a typed DOM event handler through the mixin system.
68
+ *
69
+ * @param type Event type to listen for.
70
+ * @param handler Event handler.
71
+ * @param captureBoolean Whether to listen during capture.
72
+ * @returns A mixin descriptor for the target element.
73
+ */
74
+ export function on<
75
+ target extends Element = Element,
76
+ type extends EventType<target> = EventType<target>,
77
+ >(
78
+ type: type,
79
+ handler: ListenerFor<target, type>,
80
+ captureBoolean?: boolean,
81
+ ): MixinDescriptor<target, [type, ListenerFor<target, type>, boolean?], ElementProps> {
82
+ // Keep this typed wrapper so JSX host context can infer event/currentTarget
83
+ // from `type`, rather than exposing the raw `string` + `Event` runtime signature.
84
+ return onMixin(
85
+ type as string,
86
+ handler as unknown as SignaledListener<Event>,
87
+ captureBoolean,
88
+ ) as unknown as MixinDescriptor<target, [type, ListenerFor<target, type>, boolean?], ElementProps>
89
+ }
@@ -0,0 +1,32 @@
1
+ import { createMixin } from './mixin.ts'
2
+ import type { ElementProps } from '../jsx.ts'
3
+
4
+ /**
5
+ * Callback invoked with the bound node and a lifetime signal.
6
+ */
7
+ export type RefCallback<node extends EventTarget> = (node: node, signal: AbortSignal) => void
8
+
9
+ /**
10
+ * Calls a callback when an element is inserted and aborts it when removed.
11
+ */
12
+ export const ref = createMixin<Element, [callback: RefCallback<Element>], ElementProps>(
13
+ (handle) => {
14
+ let controller: AbortController | undefined
15
+
16
+ handle.addEventListener('insert', (event) => {
17
+ controller = new AbortController()
18
+ callback(event.node, controller.signal)
19
+ })
20
+
21
+ handle.addEventListener('remove', () => {
22
+ controller?.abort(new DOMException('', 'AbortError'))
23
+ controller = undefined
24
+ })
25
+
26
+ let callback: RefCallback<Element> = () => {}
27
+ return (nextCallback) => {
28
+ callback = nextCallback
29
+ return handle.element
30
+ }
31
+ },
32
+ )
@@ -0,0 +1,136 @@
1
+ import { getTopFrame, getNamedFrame } from './run.ts'
2
+
3
+ type NavigationState = {
4
+ target: string | undefined
5
+ src: string
6
+ resetScroll: boolean
7
+ $rmx: true
8
+ }
9
+
10
+ type SourceElementNavigateEvent = NavigateEvent & {
11
+ sourceElement?: Element | null
12
+ }
13
+
14
+ /**
15
+ * Options for client-side frame-aware navigation.
16
+ */
17
+ export type NavigationOptions = {
18
+ src?: string
19
+ target?: string
20
+ history?: 'push' | 'replace'
21
+ resetScroll?: boolean
22
+ }
23
+
24
+ /**
25
+ * Performs a Navigation API transition understood by Remix frame runtime state.
26
+ *
27
+ * @param href Destination URL.
28
+ * @param options Navigation options.
29
+ */
30
+ export async function navigate(href: string, options?: NavigationOptions) {
31
+ let state = {
32
+ target: options?.target,
33
+ src: options?.src ?? href,
34
+ resetScroll: options?.resetScroll !== false,
35
+ $rmx: true,
36
+ } satisfies NavigationState
37
+ let transition = window.navigation.navigate(href, { state, history: options?.history })
38
+ await transition.finished
39
+ }
40
+
41
+ /**
42
+ * Starts listening for Navigation API transitions and routes them through frame reloads.
43
+ *
44
+ * @param signal Abort signal used to remove the listener.
45
+ */
46
+ export function startNavigationListener(signal: AbortSignal) {
47
+ let navigation = window.navigation
48
+
49
+ navigation.updateCurrentEntry({
50
+ state: { target: undefined, src: window.location.href, resetScroll: true, $rmx: true },
51
+ })
52
+
53
+ navigation.addEventListener(
54
+ 'navigate',
55
+ (event) => {
56
+ if (!event.canIntercept) return
57
+
58
+ let state = getRuntimeNavigationState(event)
59
+ if (!state) return
60
+
61
+ let topFrame = getTopFrame()
62
+ let namedFrame = state.target ? getNamedFrame(state.target) : undefined
63
+ let frame = namedFrame ?? topFrame
64
+
65
+ event.intercept({
66
+ async handler() {
67
+ if (event.navigationType !== 'traverse') {
68
+ navigation.updateCurrentEntry({ state })
69
+ }
70
+
71
+ frame.src = frame === topFrame ? event.destination.url : state.src
72
+ await frame.reload()
73
+
74
+ let isNewEntry = event.navigationType === 'push' || event.navigationType === 'replace'
75
+ if (state.resetScroll && isNewEntry) {
76
+ window.scrollTo(0, 0)
77
+ }
78
+ },
79
+ })
80
+ },
81
+ { signal },
82
+ )
83
+ }
84
+
85
+ function isRuntimeNavigation(info: unknown): info is NavigationState {
86
+ return typeof info === 'object' && info != null && '$rmx' in info
87
+ }
88
+
89
+ function getRuntimeNavigationState(event: NavigateEvent): NavigationState | undefined {
90
+ if (event.navigationType === 'traverse') {
91
+ return getTraverseNavigationState(event)
92
+ }
93
+
94
+ let sourceState = getSourceElementNavigationState(event)
95
+ if (sourceState) return sourceState
96
+
97
+ let destinationState = event.destination.getState()
98
+ if (isRuntimeNavigation(destinationState)) return destinationState
99
+ }
100
+
101
+ function getTraverseNavigationState(event: NavigateEvent): NavigationState | undefined {
102
+ let destinationState = event.destination.getState()
103
+ if (isRuntimeNavigation(destinationState)) {
104
+ return destinationState
105
+ }
106
+
107
+ // Safari returns `null` for destination.getState(), even though its in the
108
+ // navigation.entries(), so we do its job for it and look it up.
109
+ let navigation = window.navigation
110
+ let matchingEntry = navigation.entries().find((entry) => entry.key === event.destination.key)
111
+ if (matchingEntry) {
112
+ let state = matchingEntry.getState()
113
+ if (isRuntimeNavigation(state)) {
114
+ return state
115
+ }
116
+ }
117
+
118
+ return undefined
119
+ }
120
+
121
+ function getSourceElementNavigationState(event: NavigateEvent): NavigationState | undefined {
122
+ let sourceEvent = event as SourceElementNavigateEvent
123
+ let sourceElement = sourceEvent.sourceElement
124
+ if (!(sourceElement instanceof Element)) return
125
+ let linkElement = sourceElement.closest('a, area')
126
+ if (!(linkElement instanceof Element)) return
127
+ if (linkElement.hasAttribute('rmx-document')) return
128
+ if (linkElement.hasAttribute('download')) return
129
+
130
+ return {
131
+ target: linkElement.getAttribute('rmx-target') ?? undefined,
132
+ src: linkElement.getAttribute('rmx-src') ?? event.destination.url,
133
+ resetScroll: linkElement.getAttribute('rmx-reset-scroll') !== 'false',
134
+ $rmx: true,
135
+ } satisfies NavigationState
136
+ }