@bquery/bquery 1.10.0 → 1.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 (155) hide show
  1. package/README.md +44 -19
  2. package/dist/{a11y-DG2i4iZN.js → a11y-DgUQ8-fI.js} +1 -1
  3. package/dist/{a11y-DG2i4iZN.js.map → a11y-DgUQ8-fI.js.map} +1 -1
  4. package/dist/a11y.es.mjs +1 -1
  5. package/dist/{component-DRotf1hl.js → component-D8ydhe58.js} +2 -2
  6. package/dist/{component-DRotf1hl.js.map → component-D8ydhe58.js.map} +1 -1
  7. package/dist/component.es.mjs +1 -1
  8. package/dist/concurrency-BU1wPEsZ.js.map +1 -1
  9. package/dist/{constraints-CqjhmpZC.js → constraints-Dlbx_m1b.js} +1 -1
  10. package/dist/{constraints-CqjhmpZC.js.map → constraints-Dlbx_m1b.js.map} +1 -1
  11. package/dist/{core-EMYSLzaT.js → core-tOP6QOrY.js} +2 -2
  12. package/dist/{core-EMYSLzaT.js.map → core-tOP6QOrY.js.map} +1 -1
  13. package/dist/core.es.mjs +1 -1
  14. package/dist/{custom-directives-BjFzFhuf.js → custom-directives-5DlKqvd2.js} +1 -1
  15. package/dist/{custom-directives-BjFzFhuf.js.map → custom-directives-5DlKqvd2.js.map} +1 -1
  16. package/dist/{devtools-C5FExMwv.js → devtools-QosAqo0T.js} +2 -2
  17. package/dist/{devtools-C5FExMwv.js.map → devtools-QosAqo0T.js.map} +1 -1
  18. package/dist/devtools.es.mjs +1 -1
  19. package/dist/{dnd-BAqzPlSo.js → dnd-d2OU4len.js} +1 -1
  20. package/dist/{dnd-BAqzPlSo.js.map → dnd-d2OU4len.js.map} +1 -1
  21. package/dist/dnd.es.mjs +1 -1
  22. package/dist/{forms-Dx1Scvh0.js → forms-BLx4ZzT7.js} +1 -1
  23. package/dist/{forms-Dx1Scvh0.js.map → forms-BLx4ZzT7.js.map} +1 -1
  24. package/dist/forms.es.mjs +1 -1
  25. package/dist/full.d.ts +4 -2
  26. package/dist/full.d.ts.map +1 -1
  27. package/dist/full.es.mjs +258 -219
  28. package/dist/full.iife.js +41 -37
  29. package/dist/full.iife.js.map +1 -1
  30. package/dist/full.umd.js +41 -37
  31. package/dist/full.umd.js.map +1 -1
  32. package/dist/{i18n-Cazyk9RD.js → i18n--p7PM-9r.js} +1 -1
  33. package/dist/{i18n-Cazyk9RD.js.map → i18n--p7PM-9r.js.map} +1 -1
  34. package/dist/i18n.es.mjs +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.es.mjs +291 -252
  38. package/dist/match-CrZRVC4z.js +174 -0
  39. package/dist/match-CrZRVC4z.js.map +1 -0
  40. package/dist/{media-dAKIGPk3.js → media-gjbWNq50.js} +1 -1
  41. package/dist/{media-dAKIGPk3.js.map → media-gjbWNq50.js.map} +1 -1
  42. package/dist/media.es.mjs +1 -1
  43. package/dist/motion-BBMso9Ir.js.map +1 -1
  44. package/dist/{mount-C8O2vXkQ.js → mount-0A9qtcRJ.js} +3 -3
  45. package/dist/{mount-C8O2vXkQ.js.map → mount-0A9qtcRJ.js.map} +1 -1
  46. package/dist/platform-BPHIXbw8.js.map +1 -1
  47. package/dist/{plugin-DjTqWg-P.js → plugin-SZEirbwq.js} +2 -2
  48. package/dist/{plugin-DjTqWg-P.js.map → plugin-SZEirbwq.js.map} +1 -1
  49. package/dist/plugin.es.mjs +1 -1
  50. package/dist/reactive-BAd2hfl8.js.map +1 -1
  51. package/dist/{registry-Cr6VH8CR.js → registry-jpUQHf4E.js} +1 -1
  52. package/dist/{registry-Cr6VH8CR.js.map → registry-jpUQHf4E.js.map} +1 -1
  53. package/dist/router-C4weu0QL.js +333 -0
  54. package/dist/router-C4weu0QL.js.map +1 -0
  55. package/dist/router.es.mjs +1 -1
  56. package/dist/{sanitize-B1V4JswB.js → sanitize-DOMkRO9G.js} +12 -7
  57. package/dist/{sanitize-B1V4JswB.js.map → sanitize-DOMkRO9G.js.map} +1 -1
  58. package/dist/security.es.mjs +1 -1
  59. package/dist/server/create-server.d.ts +25 -0
  60. package/dist/server/create-server.d.ts.map +1 -0
  61. package/dist/server/index.d.ts +11 -0
  62. package/dist/server/index.d.ts.map +1 -0
  63. package/dist/server/types.d.ts +396 -0
  64. package/dist/server/types.d.ts.map +1 -0
  65. package/dist/server-QdyKtCS1.js +349 -0
  66. package/dist/server-QdyKtCS1.js.map +1 -0
  67. package/dist/server.es.mjs +6 -0
  68. package/dist/ssr/adapters.d.ts +74 -0
  69. package/dist/ssr/adapters.d.ts.map +1 -0
  70. package/dist/ssr/async.d.ts +40 -0
  71. package/dist/ssr/async.d.ts.map +1 -0
  72. package/dist/ssr/config.d.ts +60 -0
  73. package/dist/ssr/config.d.ts.map +1 -0
  74. package/dist/ssr/context.d.ts +73 -0
  75. package/dist/ssr/context.d.ts.map +1 -0
  76. package/dist/ssr/defer-brand.d.ts +5 -0
  77. package/dist/ssr/defer-brand.d.ts.map +1 -0
  78. package/dist/ssr/escape.d.ts +17 -0
  79. package/dist/ssr/escape.d.ts.map +1 -0
  80. package/dist/ssr/expression.d.ts +44 -0
  81. package/dist/ssr/expression.d.ts.map +1 -0
  82. package/dist/ssr/hash.d.ts +39 -0
  83. package/dist/ssr/hash.d.ts.map +1 -0
  84. package/dist/ssr/head.d.ts +102 -0
  85. package/dist/ssr/head.d.ts.map +1 -0
  86. package/dist/ssr/html-parser.d.ts +58 -0
  87. package/dist/ssr/html-parser.d.ts.map +1 -0
  88. package/dist/ssr/index.d.ts +49 -43
  89. package/dist/ssr/index.d.ts.map +1 -1
  90. package/dist/ssr/mismatch.d.ts +60 -0
  91. package/dist/ssr/mismatch.d.ts.map +1 -0
  92. package/dist/ssr/render-async.d.ts +84 -0
  93. package/dist/ssr/render-async.d.ts.map +1 -0
  94. package/dist/ssr/render.d.ts.map +1 -1
  95. package/dist/ssr/renderer.d.ts +25 -0
  96. package/dist/ssr/renderer.d.ts.map +1 -0
  97. package/dist/ssr/resumability.d.ts +65 -0
  98. package/dist/ssr/resumability.d.ts.map +1 -0
  99. package/dist/ssr/router-bridge.d.ts +101 -0
  100. package/dist/ssr/router-bridge.d.ts.map +1 -0
  101. package/dist/ssr/runtime.d.ts +63 -0
  102. package/dist/ssr/runtime.d.ts.map +1 -0
  103. package/dist/ssr/serialize.d.ts.map +1 -1
  104. package/dist/ssr/store-snapshot.d.ts +87 -0
  105. package/dist/ssr/store-snapshot.d.ts.map +1 -0
  106. package/dist/ssr/strategies.d.ts +43 -0
  107. package/dist/ssr/strategies.d.ts.map +1 -0
  108. package/dist/ssr/suspense.d.ts +47 -0
  109. package/dist/ssr/suspense.d.ts.map +1 -0
  110. package/dist/ssr/types.d.ts +17 -0
  111. package/dist/ssr/types.d.ts.map +1 -1
  112. package/dist/ssr-Bt6BQA3J.js +2127 -0
  113. package/dist/ssr-Bt6BQA3J.js.map +1 -0
  114. package/dist/ssr.es.mjs +42 -7
  115. package/dist/{store-CjmEeX9-.js → store-DnXuu6Li.js} +2 -2
  116. package/dist/{store-CjmEeX9-.js.map → store-DnXuu6Li.js.map} +1 -1
  117. package/dist/store.es.mjs +2 -2
  118. package/dist/storybook.es.mjs +1 -1
  119. package/dist/{testing-TdfaL7VE.js → testing-CeMUwrRD.js} +2 -2
  120. package/dist/{testing-TdfaL7VE.js.map → testing-CeMUwrRD.js.map} +1 -1
  121. package/dist/testing.es.mjs +1 -1
  122. package/dist/view.es.mjs +1 -1
  123. package/package.json +17 -12
  124. package/src/full.ts +99 -0
  125. package/src/index.ts +3 -0
  126. package/src/server/create-server.ts +754 -0
  127. package/src/server/index.ts +33 -0
  128. package/src/server/types.ts +490 -0
  129. package/src/ssr/adapters.ts +330 -0
  130. package/src/ssr/async.ts +125 -0
  131. package/src/ssr/config.ts +86 -0
  132. package/src/ssr/context.ts +245 -0
  133. package/src/ssr/defer-brand.ts +3 -0
  134. package/src/ssr/escape.ts +25 -0
  135. package/src/ssr/expression.ts +669 -0
  136. package/src/ssr/hash.ts +71 -0
  137. package/src/ssr/head.ts +240 -0
  138. package/src/ssr/html-parser.ts +387 -0
  139. package/src/ssr/index.ts +136 -43
  140. package/src/ssr/mismatch.ts +110 -0
  141. package/src/ssr/render-async.ts +286 -0
  142. package/src/ssr/render.ts +130 -59
  143. package/src/ssr/renderer.ts +453 -0
  144. package/src/ssr/resumability.ts +142 -0
  145. package/src/ssr/router-bridge.ts +177 -0
  146. package/src/ssr/runtime.ts +131 -0
  147. package/src/ssr/serialize.ts +1 -27
  148. package/src/ssr/store-snapshot.ts +209 -0
  149. package/src/ssr/strategies.ts +245 -0
  150. package/src/ssr/suspense.ts +504 -0
  151. package/src/ssr/types.ts +18 -0
  152. package/dist/router-CCepRMpC.js +0 -493
  153. package/dist/router-CCepRMpC.js.map +0 -1
  154. package/dist/ssr-D-1IPcfw.js +0 -248
  155. package/dist/ssr-D-1IPcfw.js.map +0 -1
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Progressive hydration strategies.
3
+ *
4
+ * Provide thin wrappers around `hydrateMount()` that defer the hydration
5
+ * pass until a chosen trigger fires. They are runtime-safe: in non-browser
6
+ * environments they fall back to immediate hydration (or a no-op) so the
7
+ * same code path can run in tests.
8
+ *
9
+ * @module bquery/ssr
10
+ */
11
+
12
+ import type { BindingContext, View } from '../view/types';
13
+ import { hydrateMount, type HydrateMountOptions } from './hydrate';
14
+
15
+ const resolveElement = (selector: string | Element): Element | null => {
16
+ if (typeof selector !== 'string') return selector;
17
+ if (typeof document === 'undefined') return null;
18
+ try {
19
+ return document.querySelector(selector);
20
+ } catch {
21
+ return null;
22
+ }
23
+ };
24
+
25
+ const hydrateResolved = (
26
+ selector: string | Element,
27
+ context: BindingContext,
28
+ options: HydrateMountOptions
29
+ ): View | null => {
30
+ const el = resolveElement(selector);
31
+ if (!el) return null;
32
+ return hydrateMount(el, context, options);
33
+ };
34
+
35
+ const noop = (): void => {};
36
+
37
+ type LegacyMediaQueryList = MediaQueryList & {
38
+ addListener?: (listener: (event: MediaQueryListEvent | MediaQueryList) => void) => void;
39
+ removeListener?: (listener: (event: MediaQueryListEvent | MediaQueryList) => void) => void;
40
+ };
41
+
42
+ const defer = (cb: () => void): (() => void) => {
43
+ if (typeof window === 'undefined') {
44
+ cb();
45
+ return noop;
46
+ }
47
+ const ric = (window as unknown as { requestIdleCallback?: (cb: () => void) => number })
48
+ .requestIdleCallback;
49
+ if (typeof ric === 'function') {
50
+ const id = ric(cb);
51
+ return () => {
52
+ const cic = (window as unknown as { cancelIdleCallback?: (id: number) => void })
53
+ .cancelIdleCallback;
54
+ if (typeof cic === 'function') cic(id);
55
+ };
56
+ }
57
+ const id = setTimeout(cb, 1);
58
+ return () => clearTimeout(id);
59
+ };
60
+
61
+ /** Common return shape for progressive hydration. */
62
+ export interface HydrationHandle {
63
+ /** Cancels pending hydration (no-op if it has already run). */
64
+ cancel(): void;
65
+ /** Resolves with the View once hydration runs, or `null` if cancelled. */
66
+ ready: Promise<View | null>;
67
+ }
68
+
69
+ const buildHandle = (
70
+ trigger: (resolve: () => void) => () => void
71
+ ): { handle: HydrationHandle; arm: (run: () => View | null) => void } => {
72
+ let cancelled = false;
73
+ let resolveReady: (v: View | null) => void = noop;
74
+ let rejectReady: (e: unknown) => void = noop;
75
+ const ready = new Promise<View | null>((res, rej) => {
76
+ resolveReady = res;
77
+ rejectReady = rej;
78
+ });
79
+ let cleanupTrigger: () => void = noop;
80
+
81
+ const arm = (run: () => View | null): void => {
82
+ cleanupTrigger = trigger(() => {
83
+ if (cancelled) return;
84
+ try {
85
+ const view = run();
86
+ resolveReady(view);
87
+ } catch (error) {
88
+ rejectReady(error);
89
+ }
90
+ });
91
+ };
92
+
93
+ return {
94
+ handle: {
95
+ ready,
96
+ cancel() {
97
+ if (cancelled) return;
98
+ cancelled = true;
99
+ cleanupTrigger();
100
+ resolveReady(null);
101
+ },
102
+ },
103
+ arm,
104
+ };
105
+ };
106
+
107
+ /**
108
+ * Hydrates the target only once it scrolls into view.
109
+ *
110
+ * Falls back to immediate hydration if `IntersectionObserver` is unavailable.
111
+ */
112
+ export const hydrateOnVisible = (
113
+ selector: string | Element,
114
+ context: BindingContext,
115
+ options: HydrateMountOptions & { rootMargin?: string; threshold?: number } = {}
116
+ ): HydrationHandle => {
117
+ const { rootMargin, threshold, ...mountOptions } = options;
118
+ const { handle, arm } = buildHandle((resolve) => {
119
+ const el = resolveElement(selector);
120
+ if (!el) {
121
+ resolve();
122
+ return noop;
123
+ }
124
+ if (typeof IntersectionObserver === 'undefined') {
125
+ resolve();
126
+ return noop;
127
+ }
128
+ const observer = new IntersectionObserver(
129
+ (entries) => {
130
+ for (const entry of entries) {
131
+ if (entry.isIntersecting) {
132
+ observer.disconnect();
133
+ resolve();
134
+ return;
135
+ }
136
+ }
137
+ },
138
+ { rootMargin: rootMargin ?? '0px', threshold: threshold ?? 0 }
139
+ );
140
+ observer.observe(el);
141
+ return () => observer.disconnect();
142
+ });
143
+
144
+ arm(() => hydrateResolved(selector, context, mountOptions));
145
+ return handle;
146
+ };
147
+
148
+ /** Hydrates when the browser is idle. */
149
+ export const hydrateOnIdle = (
150
+ selector: string | Element,
151
+ context: BindingContext,
152
+ options: HydrateMountOptions = {}
153
+ ): HydrationHandle => {
154
+ const { handle, arm } = buildHandle((resolve) => defer(resolve));
155
+ arm(() => hydrateResolved(selector, context, options));
156
+ return handle;
157
+ };
158
+
159
+ /** Hydrates on first user interaction (click/keydown/pointerdown/touchstart). */
160
+ export const hydrateOnInteraction = (
161
+ selector: string | Element,
162
+ context: BindingContext,
163
+ options: HydrateMountOptions & { events?: string[] } = {}
164
+ ): HydrationHandle => {
165
+ const events = options.events ?? ['pointerdown', 'click', 'keydown', 'touchstart', 'focusin'];
166
+ const { events: _events, ...mountOptions } = options;
167
+ const { handle, arm } = buildHandle((resolve) => {
168
+ const el = resolveElement(selector);
169
+ if (!el) {
170
+ resolve();
171
+ return noop;
172
+ }
173
+ const listener = () => {
174
+ cleanup();
175
+ resolve();
176
+ };
177
+ const cleanup = (): void => {
178
+ for (const evt of events) {
179
+ el.removeEventListener(evt, listener, true);
180
+ }
181
+ };
182
+ for (const evt of events) {
183
+ el.addEventListener(evt, listener, { once: true, capture: true });
184
+ }
185
+ return cleanup;
186
+ });
187
+ arm(() => hydrateResolved(selector, context, mountOptions));
188
+ return handle;
189
+ };
190
+
191
+ /** Hydrates only when a media query matches. */
192
+ export const hydrateOnMedia = (
193
+ selector: string | Element,
194
+ context: BindingContext,
195
+ query: string,
196
+ options: HydrateMountOptions = {}
197
+ ): HydrationHandle => {
198
+ const { handle, arm } = buildHandle((resolve) => {
199
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
200
+ resolve();
201
+ return noop;
202
+ }
203
+ const mql = window.matchMedia(query);
204
+ if (mql.matches) {
205
+ resolve();
206
+ return noop;
207
+ }
208
+ let cleanup: () => void = noop;
209
+ const listener = (event: MediaQueryListEvent | MediaQueryList): void => {
210
+ if (event.matches) {
211
+ cleanup();
212
+ resolve();
213
+ }
214
+ };
215
+ if (typeof mql.addEventListener === 'function') {
216
+ mql.addEventListener('change', listener);
217
+ cleanup = () => mql.removeEventListener('change', listener);
218
+ return cleanup;
219
+ }
220
+ const legacyMql = mql as LegacyMediaQueryList;
221
+ if (
222
+ typeof legacyMql.addListener === 'function' &&
223
+ typeof legacyMql.removeListener === 'function'
224
+ ) {
225
+ legacyMql.addListener(listener);
226
+ cleanup = () => legacyMql.removeListener(listener);
227
+ return cleanup;
228
+ }
229
+ resolve();
230
+ return noop;
231
+ });
232
+ arm(() => hydrateResolved(selector, context, options));
233
+ return handle;
234
+ };
235
+
236
+ /**
237
+ * Hydrates a single SSR island using the same runtime-safe target resolution
238
+ * as the other progressive hydration helpers. Returns `null` when the DOM is
239
+ * unavailable or the target cannot be resolved.
240
+ */
241
+ export const hydrateIsland = (
242
+ selector: string | Element,
243
+ context: BindingContext,
244
+ options: HydrateMountOptions = {}
245
+ ): View | null => hydrateResolved(selector, context, options);