@tanstack/redact 0.0.21 → 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 (253) hide show
  1. package/dist/core/attributes.js +2 -1
  2. package/dist/core/attributes.js.map +2 -2
  3. package/dist/core/browser.d.ts +9 -0
  4. package/dist/core/browser.js +35 -0
  5. package/dist/core/browser.js.map +7 -0
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +3 -3
  8. package/dist/core/internal.d.ts +31 -8
  9. package/dist/core/internal.js +3 -1
  10. package/dist/core/internal.js.map +2 -2
  11. package/dist/core/resource-hints.d.ts +7 -0
  12. package/dist/core/resource-hints.js +19 -0
  13. package/dist/core/resource-hints.js.map +7 -0
  14. package/dist/core/types.js +1 -1
  15. package/dist/dom/_all.d.ts +11 -16
  16. package/dist/dom/_all.js +9 -20
  17. package/dist/dom/_all.js.map +2 -2
  18. package/dist/dom/client.d.ts +4 -4
  19. package/dist/dom/client.js +4 -4
  20. package/dist/dom/commit.d.ts +23 -0
  21. package/dist/dom/commit.js +191 -0
  22. package/dist/dom/commit.js.map +7 -0
  23. package/dist/dom/dispatcher.d.ts +4 -22
  24. package/dist/dom/dispatcher.js +184 -126
  25. package/dist/dom/dispatcher.js.map +3 -3
  26. package/dist/dom/dom.d.ts +2 -0
  27. package/dist/dom/dom.js +72 -52
  28. package/dist/dom/dom.js.map +2 -2
  29. package/dist/dom/error-info.d.ts +2 -0
  30. package/dist/dom/error-info.js +16 -0
  31. package/dist/dom/error-info.js.map +7 -0
  32. package/dist/dom/event-replay.js +1 -1
  33. package/dist/dom/features/activity/full.d.ts +1 -0
  34. package/dist/dom/features/activity/full.js +162 -0
  35. package/dist/dom/features/activity/full.js.map +7 -0
  36. package/dist/dom/features/activity/index.d.ts +1 -0
  37. package/dist/dom/features/activity/index.js +3 -0
  38. package/dist/dom/features/activity/index.js.map +7 -0
  39. package/dist/dom/features/activity/stub.d.ts +1 -0
  40. package/dist/dom/features/activity/stub.js +12 -0
  41. package/dist/dom/features/activity/stub.js.map +7 -0
  42. package/dist/dom/features/class/full.js +87 -27
  43. package/dist/dom/features/class/full.js.map +2 -2
  44. package/dist/dom/features/class/index.d.ts +1 -1
  45. package/dist/dom/features/class/index.js +2 -2
  46. package/dist/dom/features/class/stub.js +3 -3
  47. package/dist/dom/features/context/full.d.ts +4 -1
  48. package/dist/dom/features/context/full.js +69 -9
  49. package/dist/dom/features/context/full.js.map +2 -2
  50. package/dist/dom/features/context/index.d.ts +1 -1
  51. package/dist/dom/features/context/index.js +2 -2
  52. package/dist/dom/features/context/stub.d.ts +4 -1
  53. package/dist/dom/features/context/stub.js +15 -4
  54. package/dist/dom/features/context/stub.js.map +2 -2
  55. package/dist/dom/features/forward-ref/full.js +12 -21
  56. package/dist/dom/features/forward-ref/full.js.map +2 -2
  57. package/dist/dom/features/forward-ref/index.d.ts +1 -1
  58. package/dist/dom/features/forward-ref/index.js +2 -2
  59. package/dist/dom/features/forward-ref/stub.js +4 -4
  60. package/dist/dom/features/fragment-refs/index.d.ts +1 -0
  61. package/dist/dom/features/fragment-refs/index.js +8 -0
  62. package/dist/dom/features/fragment-refs/index.js.map +7 -0
  63. package/dist/dom/features/fragment-refs/stub.d.ts +3 -0
  64. package/dist/dom/features/fragment-refs/stub.js +14 -0
  65. package/dist/dom/features/fragment-refs/stub.js.map +7 -0
  66. package/dist/dom/features/hydration/full.d.ts +11 -6
  67. package/dist/dom/features/hydration/full.js +76 -77
  68. package/dist/dom/features/hydration/full.js.map +2 -2
  69. package/dist/dom/features/hydration/index.d.ts +1 -1
  70. package/dist/dom/features/hydration/index.js +2 -2
  71. package/dist/dom/features/hydration/stub.d.ts +7 -2
  72. package/dist/dom/features/hydration/stub.js +1 -1
  73. package/dist/dom/features/hydration/stub.js.map +1 -1
  74. package/dist/dom/features/index.d.ts +8 -7
  75. package/dist/dom/features/index.js +9 -8
  76. package/dist/dom/features/index.js.map +2 -2
  77. package/dist/dom/features/lazy/full.js +4 -4
  78. package/dist/dom/features/lazy/index.d.ts +1 -1
  79. package/dist/dom/features/lazy/index.js +2 -2
  80. package/dist/dom/features/lazy/stub.js +4 -4
  81. package/dist/dom/features/memo/full.js +8 -6
  82. package/dist/dom/features/memo/full.js.map +2 -2
  83. package/dist/dom/features/memo/index.d.ts +1 -1
  84. package/dist/dom/features/memo/index.js +2 -2
  85. package/dist/dom/features/memo/stub.js +4 -4
  86. package/dist/dom/features/portal/full.js +4 -4
  87. package/dist/dom/features/portal/index.d.ts +1 -1
  88. package/dist/dom/features/portal/index.js +2 -2
  89. package/dist/dom/features/portal/stub.js +4 -4
  90. package/dist/dom/features/suspense/full.js +197 -52
  91. package/dist/dom/features/suspense/full.js.map +2 -2
  92. package/dist/dom/features/suspense/index.d.ts +1 -1
  93. package/dist/dom/features/suspense/index.js +2 -2
  94. package/dist/dom/features/suspense/stub.js +4 -4
  95. package/dist/dom/features/view-transition/full.d.ts +6 -0
  96. package/dist/dom/features/view-transition/full.js +280 -0
  97. package/dist/dom/features/view-transition/full.js.map +7 -0
  98. package/dist/dom/features/view-transition/index.d.ts +1 -0
  99. package/dist/dom/features/view-transition/index.js +3 -0
  100. package/dist/dom/features/view-transition/index.js.map +7 -0
  101. package/dist/dom/features/view-transition/resources.d.ts +11 -0
  102. package/dist/dom/features/view-transition/resources.js +108 -0
  103. package/dist/dom/features/view-transition/resources.js.map +7 -0
  104. package/dist/dom/features/view-transition/stub.d.ts +6 -0
  105. package/dist/dom/features/view-transition/stub.js +22 -0
  106. package/dist/dom/features/view-transition/stub.js.map +7 -0
  107. package/dist/dom/features/view-transition/visual.d.ts +14 -0
  108. package/dist/dom/features/view-transition/visual.js +356 -0
  109. package/dist/dom/features/view-transition/visual.js.map +7 -0
  110. package/dist/dom/fragment-instance.d.ts +40 -0
  111. package/dist/dom/fragment-instance.js +324 -0
  112. package/dist/dom/fragment-instance.js.map +7 -0
  113. package/dist/dom/index.d.ts +11 -11
  114. package/dist/dom/index.js +11 -18
  115. package/dist/dom/index.js.map +3 -3
  116. package/dist/dom/portal.d.ts +2 -2
  117. package/dist/dom/portal.js +2 -2
  118. package/dist/dom/portal.js.map +1 -1
  119. package/dist/dom/reconcile.d.ts +32 -3
  120. package/dist/dom/reconcile.js +689 -221
  121. package/dist/dom/reconcile.js.map +2 -2
  122. package/dist/dom/resource-hints.d.ts +6 -0
  123. package/dist/dom/resource-hints.js +115 -0
  124. package/dist/dom/resource-hints.js.map +7 -0
  125. package/dist/dom/resource-store.d.ts +13 -0
  126. package/dist/dom/resource-store.js +43 -0
  127. package/dist/dom/resource-store.js.map +7 -0
  128. package/dist/dom/resources.d.ts +1 -0
  129. package/dist/dom/resources.js +44 -0
  130. package/dist/dom/resources.js.map +7 -0
  131. package/dist/dom/retained-effects.d.ts +6 -0
  132. package/dist/dom/retained-effects.js +49 -0
  133. package/dist/dom/retained-effects.js.map +7 -0
  134. package/dist/dom/root-internal.d.ts +4 -4
  135. package/dist/dom/root-internal.js +2 -2
  136. package/dist/dom/root-internal.js.map +2 -2
  137. package/dist/dom/root.d.ts +5 -5
  138. package/dist/dom/root.js +11 -11
  139. package/dist/dom/root.js.map +2 -2
  140. package/dist/dom/test-utils.js +1 -1
  141. package/dist/react/activity.d.ts +7 -0
  142. package/dist/react/activity.js +8 -0
  143. package/dist/react/activity.js.map +7 -0
  144. package/dist/react/children.d.ts +1 -1
  145. package/dist/react/children.js +3 -3
  146. package/dist/react/children.js.map +1 -1
  147. package/dist/react/class.d.ts +1 -1
  148. package/dist/react/class.js +3 -3
  149. package/dist/react/class.js.map +1 -1
  150. package/dist/react/compiler-runtime.js +2 -2
  151. package/dist/react/context.d.ts +1 -1
  152. package/dist/react/context.js +3 -3
  153. package/dist/react/context.js.map +1 -1
  154. package/dist/react/element.d.ts +6 -3
  155. package/dist/react/element.js +2 -2
  156. package/dist/react/element.js.map +2 -2
  157. package/dist/react/hooks.d.ts +26 -7
  158. package/dist/react/hooks.js +13 -3
  159. package/dist/react/hooks.js.map +2 -2
  160. package/dist/react/index.d.ts +39 -24
  161. package/dist/react/index.js +39 -19
  162. package/dist/react/index.js.map +3 -3
  163. package/dist/react/jsx-runtime.d.ts +2 -2
  164. package/dist/react/jsx-runtime.js +3 -3
  165. package/dist/react/memo.d.ts +1 -1
  166. package/dist/react/memo.js +1 -1
  167. package/dist/react/portal.js +1 -1
  168. package/dist/react/shared-internals.d.ts +15 -5
  169. package/dist/react/shared-internals.js +2 -3
  170. package/dist/react/shared-internals.js.map +2 -2
  171. package/dist/react/suspense.js +1 -1
  172. package/dist/react/view-transition.d.ts +32 -0
  173. package/dist/react/view-transition.js +13 -0
  174. package/dist/react/view-transition.js.map +7 -0
  175. package/dist/scheduler/index.js +1 -1
  176. package/dist/server/bootstrap-script.d.ts +1 -23
  177. package/dist/server/bootstrap-script.js +7 -6
  178. package/dist/server/bootstrap-script.js.map +2 -2
  179. package/dist/server/dispatcher.d.ts +28 -6
  180. package/dist/server/dispatcher.js +33 -15
  181. package/dist/server/dispatcher.js.map +2 -2
  182. package/dist/server/escape.js +16 -15
  183. package/dist/server/escape.js.map +2 -2
  184. package/dist/server/index.d.ts +6 -6
  185. package/dist/server/index.js +7 -7
  186. package/dist/server/renderToString.d.ts +1 -1
  187. package/dist/server/renderToString.js +12 -8
  188. package/dist/server/renderToString.js.map +2 -2
  189. package/dist/server/resource-hints.d.ts +22 -0
  190. package/dist/server/resource-hints.js +148 -0
  191. package/dist/server/resource-hints.js.map +7 -0
  192. package/dist/server/stream.d.ts +15 -2
  193. package/dist/server/stream.js +155 -63
  194. package/dist/server/stream.js.map +2 -2
  195. package/dist/server/walk.d.ts +15 -2
  196. package/dist/server/walk.js +143 -96
  197. package/dist/server/walk.js.map +2 -2
  198. package/dist/vite/index.d.ts +6 -0
  199. package/dist/vite/index.js +22 -6
  200. package/dist/vite/index.js.map +2 -2
  201. package/package.json +1 -1
  202. package/src/core/attributes.ts +1 -0
  203. package/src/core/browser.ts +33 -0
  204. package/src/core/internal.ts +24 -6
  205. package/src/core/resource-hints.ts +36 -0
  206. package/src/dom/_all.ts +1 -7
  207. package/src/dom/commit.ts +186 -0
  208. package/src/dom/dispatcher.ts +190 -134
  209. package/src/dom/dom.ts +70 -54
  210. package/src/dom/error-info.ts +15 -0
  211. package/src/dom/features/activity/full.ts +166 -0
  212. package/src/dom/features/activity/index.ts +1 -0
  213. package/src/dom/features/activity/stub.ts +14 -0
  214. package/src/dom/features/class/full.ts +72 -28
  215. package/src/dom/features/context/full.ts +66 -4
  216. package/src/dom/features/context/stub.ts +6 -0
  217. package/src/dom/features/forward-ref/full.ts +9 -19
  218. package/src/dom/features/fragment-refs/index.ts +1 -0
  219. package/src/dom/features/fragment-refs/stub.ts +3 -0
  220. package/src/dom/features/hydration/full.ts +84 -85
  221. package/src/dom/features/hydration/stub.ts +1 -1
  222. package/src/dom/features/index.ts +1 -0
  223. package/src/dom/features/memo/full.ts +4 -3
  224. package/src/dom/features/suspense/full.ts +192 -55
  225. package/src/dom/features/view-transition/full.ts +288 -0
  226. package/src/dom/features/view-transition/index.ts +1 -0
  227. package/src/dom/features/view-transition/resources.ts +107 -0
  228. package/src/dom/features/view-transition/stub.ts +7 -0
  229. package/src/dom/features/view-transition/visual.ts +406 -0
  230. package/src/dom/fragment-instance.ts +337 -0
  231. package/src/dom/index.ts +6 -7
  232. package/src/dom/portal.ts +1 -1
  233. package/src/dom/reconcile.ts +695 -242
  234. package/src/dom/resource-hints.ts +115 -0
  235. package/src/dom/resource-store.ts +52 -0
  236. package/src/dom/resources.ts +39 -0
  237. package/src/dom/retained-effects.ts +38 -0
  238. package/src/dom/root-internal.ts +4 -4
  239. package/src/dom/root.ts +12 -14
  240. package/src/react/activity.ts +10 -0
  241. package/src/react/element.ts +6 -2
  242. package/src/react/hooks.ts +12 -3
  243. package/src/react/index.ts +18 -0
  244. package/src/react/shared-internals.ts +3 -3
  245. package/src/react/view-transition.ts +41 -0
  246. package/src/server/bootstrap-script.ts +36 -5
  247. package/src/server/dispatcher.ts +35 -13
  248. package/src/server/escape.ts +15 -12
  249. package/src/server/renderToString.ts +7 -5
  250. package/src/server/resource-hints.ts +165 -0
  251. package/src/server/stream.ts +154 -62
  252. package/src/server/walk.ts +72 -11
  253. package/src/vite/index.ts +30 -13
@@ -0,0 +1,337 @@
1
+ import { FiberTag, type Fiber, type FiberRoot } from '../core'
2
+ import { findRoot, getCurrentRoot, isActivityHidden } from './reconcile'
3
+ import { onCommitFailure, onCommitRollback, queueMutation } from './commit'
4
+
5
+ type Listener = EventListenerOrEventListenerObject
6
+ type Observer = IntersectionObserver | ResizeObserver
7
+ type OwnedNode = Node & { reactFragments?: Set<FragmentInstance> }
8
+ type Registration = {
9
+ type: string
10
+ listener: Listener
11
+ attached: Listener
12
+ capture: boolean
13
+ options: AddEventListenerOptions
14
+ cleanup?: () => void
15
+ }
16
+
17
+ const instances = new WeakMap<FiberRoot, Set<FragmentInstance>>()
18
+
19
+ function hosts(fiber: Fiber, deep = false, result: Fiber[] = []): Fiber[] {
20
+ for (let child = fiber.child; child; child = child.sibling) {
21
+ if (child.um || isActivityHidden(child)) continue
22
+ const host = child.tag === FiberTag.Host || child.tag === FiberTag.Text
23
+ if (host) result.push(child)
24
+ if (!host || deep) hosts(child, deep, result)
25
+ }
26
+ if (deep && fiber.tag === FiberTag.Suspense && fiber.ms?.f) hosts(fiber.ms.f, true, result)
27
+ return result
28
+ }
29
+
30
+ function node(fiber: Fiber): Node {
31
+ return fiber.tag === FiberTag.Root ? fiber.root!.c : fiber.dom!
32
+ }
33
+
34
+ function siblings(fiber: Fiber, parent: Fiber | null): [Node | null, Node | null] {
35
+ let previous: Node | null = null
36
+ let next: Node | null = null
37
+ let found = false
38
+ function visit(parent: Fiber): void {
39
+ for (let child = parent.child; child && !next; child = child.sibling) {
40
+ if (child === fiber) found = true
41
+ else if (child.tag === FiberTag.Host || child.tag === FiberTag.Text) {
42
+ if (found) next = node(child)
43
+ else previous = node(child)
44
+ } else if (!isActivityHidden(child)) visit(child)
45
+ }
46
+ }
47
+ if (parent) visit(parent)
48
+ return [previous, next]
49
+ }
50
+
51
+ function containsFiber(parent: Fiber, child: Fiber | null): boolean {
52
+ for (; child; child = child.parent) if (child === parent) return true
53
+ return false
54
+ }
55
+
56
+ export class FragmentInstance {
57
+ private nodes = new Set<OwnedNode>()
58
+ private listeners: Registration[] = []
59
+ private observers = new Set<Observer>()
60
+ private pending = new Map<Observer, Set<Element>>()
61
+ private children: Node[] = []
62
+ private ordered: Fiber[] = []
63
+ private parent: Node | null = null
64
+ private adjacent: [Node | null, Node | null] = [null, null]
65
+ private portalContainer: Node | null = null
66
+
67
+ constructor(private fiber: Fiber) {}
68
+
69
+ refresh(ordered: Fiber[]): void {
70
+ this.children = hosts(this.fiber).map(node)
71
+ let parent = this.fiber.parent
72
+ this.portalContainer = null
73
+ for (; parent; parent = parent.parent) {
74
+ if (parent.tag === FiberTag.Host || parent.tag === FiberTag.Root) break
75
+ if (parent.tag === FiberTag.Portal && !this.portalContainer) this.portalContainer = parent.mp.container
76
+ }
77
+ this.parent = parent && node(parent)
78
+ this.adjacent = siblings(this.fiber, parent)
79
+ this.ordered = ordered
80
+ const current = new Set(this.children)
81
+ for (const child of this.nodes) if (!current.has(child)) this.update(child, false)
82
+ for (const child of current) this.update(child, true)
83
+ }
84
+
85
+ /** Renderer hook, called only for first-level host insertion/removal. */
86
+ update(child: OwnedNode, adding: boolean): void {
87
+ if (adding === this.nodes.has(child)) return
88
+ if (adding) {
89
+ this.nodes.add(child)
90
+ ;(child.reactFragments ??= new Set()).add(this)
91
+ } else {
92
+ this.nodes.delete(child)
93
+ child.reactFragments?.delete(this)
94
+ }
95
+ for (const entry of this.listeners) {
96
+ if (adding) child.addEventListener(entry.type, entry.attached, entry.options)
97
+ else child.removeEventListener(entry.type, entry.attached, entry.capture)
98
+ }
99
+ if (child.nodeType !== 1) return
100
+ for (const observer of this.observers) {
101
+ if (adding) {
102
+ this.pending.get(observer)?.delete(child as Element)
103
+ observer.observe(child as Element)
104
+ } else if (typeof (observer as IntersectionObserver).rootMargin === 'string') {
105
+ let pending = this.pending.get(observer)
106
+ if (!pending) {
107
+ this.pending.set(observer, pending = new Set())
108
+ const flush = () => {
109
+ for (const element of pending!) observer.unobserve(element)
110
+ if (this.pending.get(observer) === pending) this.pending.delete(observer)
111
+ }
112
+ const frame = child.ownerDocument?.defaultView?.requestAnimationFrame
113
+ if (frame) frame(() => frame(flush))
114
+ else queueMicrotask(flush)
115
+ }
116
+ pending.add(child as Element)
117
+ } else observer.unobserve(child as Element)
118
+ }
119
+ }
120
+
121
+ addEventListener(type: string, listener: Listener | null, options?: boolean | AddEventListenerOptions): void {
122
+ if (!listener) return
123
+ const opts = typeof options === 'boolean' ? { capture: options } : options ?? {}
124
+ const capture = !!opts.capture
125
+ if (opts.signal?.aborted || this.listeners.some((entry) => entry.type === type && entry.listener === listener && entry.capture === capture)) return
126
+ const instance = this
127
+ const entry: Registration = {
128
+ type, listener, capture,
129
+ options: opts.passive === undefined ? { capture } : { capture, passive: opts.passive },
130
+ attached: opts.once ? function (this: EventTarget, event: Event) {
131
+ instance.removeEventListener(type, listener, capture)
132
+ if (typeof listener === 'function') listener.call(this, event)
133
+ else listener.handleEvent(event)
134
+ } : listener,
135
+ }
136
+ if (opts.signal) {
137
+ const abort = () => this.removeEventListener(type, listener, capture)
138
+ opts.signal.addEventListener('abort', abort, { once: true })
139
+ entry.cleanup = () => opts.signal!.removeEventListener('abort', abort)
140
+ }
141
+ this.listeners.push(entry)
142
+ for (const child of this.nodes) child.addEventListener(type, entry.attached, entry.options)
143
+ }
144
+
145
+ removeEventListener(type: string, listener: Listener | null, options?: boolean | EventListenerOptions): void {
146
+ const capture = typeof options === 'boolean' ? options : !!options?.capture
147
+ const index = this.listeners.findIndex((entry) => entry.type === type && entry.listener === listener && entry.capture === capture)
148
+ if (index < 0) return
149
+ const entry = this.listeners.splice(index, 1)[0]!
150
+ for (const child of this.nodes) child.removeEventListener(type, entry.attached, capture)
151
+ entry.cleanup?.()
152
+ }
153
+
154
+ dispatchEvent(event: Event): boolean {
155
+ const parent = !this.fiber.um && this.parent
156
+ if (!parent) return true
157
+ const target = parent
158
+ if (!this.listeners.length && event.bubbles) return target.dispatchEvent(event)
159
+ const document = target.nodeType === 9 ? target as Document : target.ownerDocument!
160
+ const temporary = target.nodeType === 9 ? document.createComment('') : document.createTextNode('')
161
+ for (const entry of this.listeners) temporary.addEventListener(entry.type, entry.attached, entry.options)
162
+ target.appendChild(temporary)
163
+ try { return temporary.dispatchEvent(event) }
164
+ finally { temporary.parentNode?.removeChild(temporary) }
165
+ }
166
+
167
+ private focusChild(last: boolean, options?: FocusOptions): void {
168
+ // Parent links survive reconciliation. Filter the committed root order,
169
+ // not the work-in-progress child pointers, when focus is actually used.
170
+ const children = this.ordered.filter(child => containsFiber(this.fiber, child))
171
+ if (last) children.reverse()
172
+ for (const child of children) {
173
+ if (child.tag === FiberTag.Text) continue
174
+ const element = child.dom as HTMLElement
175
+ if (element.ownerDocument.activeElement === element) return
176
+ let focused = false
177
+ const handleFocus = () => { focused = true }
178
+ element.ownerDocument.addEventListener('focus', handleFocus, true)
179
+ try { (element.focus ?? HTMLElement.prototype.focus).call(element, options) }
180
+ finally { element.ownerDocument.removeEventListener('focus', handleFocus, true) }
181
+ if (focused) return
182
+ }
183
+ }
184
+
185
+ focus(options?: FocusOptions): void { this.focusChild(false, options) }
186
+ focusLast(options?: FocusOptions): void { this.focusChild(true, options) }
187
+
188
+ blur(): void {
189
+ const parent = this.parent
190
+ const active = parent && (parent.ownerDocument ?? parent as Document).activeElement as HTMLElement | null
191
+ if (active && this.children.some((child) => child.contains(active))) active.blur()
192
+ }
193
+
194
+ observeUsing(observer: Observer): void {
195
+ this.observers.add(observer)
196
+ for (const child of this.nodes) if (child.nodeType === 1) observer.observe(child as Element)
197
+ }
198
+
199
+ unobserveUsing(observer: Observer): void {
200
+ if (!this.observers.delete(observer)) return
201
+ for (const child of this.nodes) if (child.nodeType === 1) observer.unobserve(child as Element)
202
+ for (const child of this.pending.get(observer) ?? []) observer.unobserve(child)
203
+ this.pending.get(observer)?.clear()
204
+ this.pending.delete(observer)
205
+ }
206
+
207
+ getClientRects(): DOMRect[] {
208
+ const rects: DOMRect[] = []
209
+ for (const child of this.children) {
210
+ if (child.nodeType === 3) {
211
+ const range = child.ownerDocument!.createRange()
212
+ range.selectNodeContents(child)
213
+ rects.push(...range.getClientRects())
214
+ } else rects.push(...(child as Element).getClientRects())
215
+ }
216
+ return rects
217
+ }
218
+
219
+ getRootNode(options?: GetRootNodeOptions): Node | FragmentInstance {
220
+ const parent = !this.fiber.um && this.parent
221
+ return parent ? parent.getRootNode(options) : this
222
+ }
223
+
224
+ compareDocumentPosition(other: Node): number {
225
+ const parent = !this.fiber.um && this.parent
226
+ if (!parent) return 1
227
+ const children = this.children
228
+ let parentNode = parent
229
+ if (!children.length) {
230
+ if (this.portalContainer) parentNode = this.portalContainer
231
+ let result = parentNode.compareDocumentPosition(other)
232
+ if (parentNode === other) result = 8
233
+ else if (result & 16) {
234
+ const following = this.adjacent[1]
235
+ const position = following && following.compareDocumentPosition(other)
236
+ result = following && (position === 0 || position! & 4) ? 4 : 2
237
+ }
238
+ return result | 32
239
+ }
240
+ const first = children[0]!
241
+ const last = children[children.length - 1]!
242
+ if (this.portalContainer) parentNode = first.parentNode!
243
+ if (!parentNode) return 1
244
+ const firstContained = parentNode.compareDocumentPosition(first) & 16
245
+ const lastContained = parentNode.compareDocumentPosition(last) & 16
246
+ const firstPosition = first.compareDocumentPosition(other)
247
+ const lastPosition = last.compareDocumentPosition(other)
248
+ const result = (firstContained && first === other) || (lastContained && last === other) ||
249
+ (firstPosition & 16) || (lastPosition & 16) ||
250
+ (firstContained && lastContained && (firstPosition & 4) && (lastPosition & 2)) ? 16 :
251
+ (!firstContained && first === other) || (!lastContained && last === other) ? 32 : firstPosition
252
+ if (result & 33) return result
253
+ const ordered = this.ordered
254
+ let otherFiber: Fiber | undefined
255
+ for (let target: Node | null = other; target && !otherFiber; target = target.parentNode) {
256
+ otherFiber = ordered.find((fiber) => fiber.dom === target)
257
+ }
258
+ if (result & 16) return containsFiber(this.fiber, otherFiber ?? null) ? result : 32
259
+ if (result & 8) return otherFiber || other === other.ownerDocument || other === other.ownerDocument?.documentElement || other === other.ownerDocument?.body ? result : 32
260
+ if (!otherFiber) return 32
261
+ const otherIndex = ordered.indexOf(otherFiber)
262
+ return ((result & 2) && otherIndex <= ordered.findIndex(fiber => fiber.dom === first)) ||
263
+ ((result & 4) && otherIndex >= ordered.findIndex(fiber => fiber.dom === last)) ? result : 32
264
+ }
265
+
266
+ scrollIntoView(alignToTop?: boolean): void {
267
+ if (typeof alignToTop === 'object') throw new Error('FragmentInstance.scrollIntoView expects a boolean, not an options object.')
268
+ if (this.fiber.um) return
269
+ const children = this.children.slice()
270
+ const top = alignToTop !== false
271
+ if (!children.length) {
272
+ const [previous, next] = this.adjacent
273
+ const fallback = top ? next ?? previous ?? this.parent : previous ?? next
274
+ if (fallback) children.push(fallback)
275
+ }
276
+ if (top) children.reverse()
277
+ for (const target of children) {
278
+ if (target.nodeType === 3) {
279
+ const range = target.ownerDocument!.createRange()
280
+ range.selectNodeContents(target)
281
+ const rect = range.getBoundingClientRect()
282
+ const window = target.ownerDocument!.defaultView!
283
+ window.scrollTo(window.scrollX + rect.left, window.scrollY + (top ? rect.top : rect.bottom - window.innerHeight))
284
+ } else if (target.nodeType === 11) {
285
+ ;(target as ShadowRoot).host?.scrollIntoView(alignToTop)
286
+ } else if (target.nodeType !== 9) (target as Element).scrollIntoView(alignToTop)
287
+ }
288
+ }
289
+
290
+ dispose(): void {
291
+ for (const child of this.nodes) this.update(child, false)
292
+ for (const entry of this.listeners) entry.cleanup?.()
293
+ this.listeners = []
294
+ this.children = []
295
+ this.ordered = []
296
+ this.parent = null
297
+ const root = this.fiber.root ?? findRoot(this.fiber)
298
+ if (root) instances.get(root)?.delete(this)
299
+ }
300
+ }
301
+
302
+ export function createFragmentInstance(fiber: Fiber): FragmentInstance {
303
+ const root = fiber.root ?? findRoot(fiber)
304
+ if (root) root.fr = true
305
+ const instance = new FragmentInstance(fiber)
306
+ if (root) {
307
+ let registered = instances.get(root)
308
+ if (!registered) instances.set(root, registered = new Set())
309
+ registered.add(instance)
310
+ onCommitRollback(() => { registered.delete(instance) })
311
+ onCommitFailure(() => { registered.delete(instance) })
312
+ }
313
+ return instance
314
+ }
315
+
316
+ export function updateFragmentHost(fiber: Fiber, adding: boolean): void {
317
+ if (!(fiber.root ?? getCurrentRoot() ?? findRoot(fiber))?.fr || !fiber.dom) return
318
+ const dom = fiber.dom
319
+ queueMutation(() => {
320
+ for (let parent = fiber.parent; parent; parent = parent.parent) {
321
+ if (adding && isActivityHidden(parent)) break
322
+ if (parent.tag === FiberTag.Fragment && parent.sn instanceof FragmentInstance) parent.sn.update(dom, adding)
323
+ if (parent.tag === FiberTag.Host || parent.tag === FiberTag.Root) break
324
+ }
325
+ })
326
+ }
327
+
328
+ export function refreshFragmentInstances(root: FiberRoot): void {
329
+ if (!root.fr) return
330
+ const registered = instances.get(root)
331
+ if (!registered?.size) return
332
+ queueMutation(() => {
333
+ if (!registered.size) return
334
+ const ordered = hosts(root.r, true)
335
+ for (const instance of registered) instance.refresh(ordered)
336
+ })
337
+ }
package/src/dom/index.ts CHANGED
@@ -5,14 +5,11 @@ import './features'
5
5
 
6
6
  export { flushSync, batchedUpdates as unstable_batchedUpdates } from './root'
7
7
  export { createPortal } from './portal'
8
+ export { browser } from '../core/browser'
9
+ export type { BrowserToken } from '../core/browser'
8
10
 
9
- // Resource hints stubs
10
- export function preconnect(_href: string, _opts?: any): void {}
11
- export function prefetchDNS(_href: string): void {}
12
- export function preload(_href: string, _opts?: any): void {}
13
- export function preinit(_href: string, _opts?: any): void {}
14
- export function preloadModule(_href: string, _opts?: any): void {}
15
- export function preinitModule(_href: string, _opts?: any): void {}
11
+ import { preconnect, prefetchDNS, preload, preinit, preloadModule, preinitModule } from './resource-hints'
12
+ export { preconnect, prefetchDNS, preload, preinit, preloadModule, preinitModule }
16
13
 
17
14
  export const __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = {
18
15
  d: {
@@ -35,10 +32,12 @@ export const version = '19.2.3'
35
32
  // Required by React's default export consumers
36
33
  import { flushSync, batchedUpdates } from './root'
37
34
  import { createPortal } from './portal'
35
+ import { browser } from '../core/browser'
38
36
  export default {
39
37
  flushSync,
40
38
  unstable_batchedUpdates: batchedUpdates,
41
39
  createPortal,
40
+ browser,
42
41
  preconnect,
43
42
  prefetchDNS,
44
43
  preload,
package/src/dom/portal.ts CHANGED
@@ -3,7 +3,7 @@ import { REACT_PORTAL_TYPE } from '../react'
3
3
 
4
4
  export function createPortal(
5
5
  children: ReactNode,
6
- container: Element,
6
+ container: Element | DocumentFragment,
7
7
  key: string | null = null,
8
8
  ): ReactElement {
9
9
  return {