@absolutejs/absolute 0.19.0-beta.704 → 0.19.0-beta.706

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 (103) hide show
  1. package/dist/angular/browser.js +6 -4
  2. package/dist/angular/browser.js.map +3 -3
  3. package/dist/angular/index.js +71 -82
  4. package/dist/angular/index.js.map +10 -10
  5. package/dist/angular/server.js +70 -81
  6. package/dist/angular/server.js.map +10 -10
  7. package/dist/build.js +152 -84
  8. package/dist/build.js.map +15 -15
  9. package/dist/cli/index.js +330 -296
  10. package/dist/client/index.js +7 -4
  11. package/dist/client/index.js.map +3 -3
  12. package/dist/index.js +253 -153
  13. package/dist/index.js.map +24 -24
  14. package/dist/islands/index.js +9 -6
  15. package/dist/islands/index.js.map +5 -5
  16. package/dist/react/browser.js +7 -7
  17. package/dist/react/browser.js.map +2 -2
  18. package/dist/react/components/browser/index.js +101 -101
  19. package/dist/react/components/index.js +104 -104
  20. package/dist/react/components/index.js.map +2 -2
  21. package/dist/react/index.js +77 -88
  22. package/dist/react/index.js.map +10 -10
  23. package/dist/react/jsxDevRuntimeCompat.js +1 -6
  24. package/dist/react/jsxDevRuntimeCompat.js.map +3 -3
  25. package/dist/react/server.js +57 -71
  26. package/dist/react/server.js.map +8 -8
  27. package/dist/src/angular/components/defer-slot-templates.directive.d.ts +0 -7
  28. package/dist/src/angular/components/defer-slot.component.d.ts +2 -5
  29. package/dist/src/angular/components/image.component.d.ts +2 -5
  30. package/dist/src/angular/components/index.d.ts +4 -4
  31. package/dist/src/angular/components/stream-slot.component.d.ts +0 -3
  32. package/dist/src/angular/pageHandler.d.ts +6 -1
  33. package/dist/src/angular/ssrRender.d.ts +1 -1
  34. package/dist/src/build/buildAngularVendor.d.ts +3 -4
  35. package/dist/src/constants.d.ts +21 -0
  36. package/dist/src/core/ssrCache.d.ts +1 -1
  37. package/dist/src/core/wrapPageHandlerWithStreamingSlots.d.ts +1 -1
  38. package/dist/src/react/jsxDevRuntimeCompat.d.ts +3 -6
  39. package/dist/src/react/pageHandler.d.ts +2 -1
  40. package/dist/src/svelte/pageHandler.d.ts +2 -2
  41. package/dist/src/utils/defineConfig.d.ts +2 -2
  42. package/dist/src/utils/imageProcessing.d.ts +1 -1
  43. package/dist/src/utils/loadConfig.d.ts +38 -2
  44. package/dist/src/vue/components/Image.d.ts +3 -3
  45. package/dist/src/vue/components/index.d.ts +1 -1
  46. package/dist/src/vue/index.d.ts +1 -1
  47. package/dist/src/vue/pageHandler.d.ts +2 -1
  48. package/dist/svelte/index.js +52 -58
  49. package/dist/svelte/index.js.map +10 -10
  50. package/dist/svelte/server.js +46 -55
  51. package/dist/svelte/server.js.map +9 -9
  52. package/dist/vue/components/Image.js +18 -18
  53. package/dist/vue/components/Image.js.map +3 -3
  54. package/dist/vue/components/index.js +77 -62
  55. package/dist/vue/components/index.js.map +5 -5
  56. package/dist/vue/index.js +137 -142
  57. package/dist/vue/index.js.map +13 -13
  58. package/dist/vue/server.js +54 -77
  59. package/dist/vue/server.js.map +8 -8
  60. package/package.json +42 -42
  61. package/dist/angular/components/constants.js +0 -56
  62. package/dist/angular/components/core/streamingSlotRegistrar.js +0 -58
  63. package/dist/angular/components/core/streamingSlotRegistry.js +0 -114
  64. package/dist/angular/components/defer-slot-payload.js +0 -6
  65. package/dist/angular/components/defer-slot-templates.directive.js +0 -44
  66. package/dist/angular/components/defer-slot.component.js +0 -149
  67. package/dist/angular/components/image.component.js +0 -202
  68. package/dist/angular/components/index.js +0 -4
  69. package/dist/angular/components/stream-slot.component.js +0 -103
  70. package/dist/dev/client/constants.ts +0 -26
  71. package/dist/dev/client/cssUtils.ts +0 -307
  72. package/dist/dev/client/domDiff.ts +0 -226
  73. package/dist/dev/client/domState.ts +0 -421
  74. package/dist/dev/client/domTracker.ts +0 -61
  75. package/dist/dev/client/errorOverlay.ts +0 -184
  76. package/dist/dev/client/frameworkDetect.ts +0 -63
  77. package/dist/dev/client/handlers/angular.ts +0 -551
  78. package/dist/dev/client/handlers/angularRuntime.ts +0 -206
  79. package/dist/dev/client/handlers/html.ts +0 -363
  80. package/dist/dev/client/handlers/htmx.ts +0 -272
  81. package/dist/dev/client/handlers/react.ts +0 -108
  82. package/dist/dev/client/handlers/rebuild.ts +0 -153
  83. package/dist/dev/client/handlers/svelte.ts +0 -332
  84. package/dist/dev/client/handlers/vue.ts +0 -292
  85. package/dist/dev/client/headPatch.ts +0 -233
  86. package/dist/dev/client/hmrClient.ts +0 -251
  87. package/dist/dev/client/hmrState.ts +0 -14
  88. package/dist/dev/client/moduleVersions.ts +0 -62
  89. package/dist/dev/client/reactRefreshSetup.ts +0 -33
  90. package/dist/src/angular/components/constants.d.ts +0 -53
  91. package/dist/svelte/components/AwaitSlot.svelte +0 -39
  92. package/dist/svelte/components/AwaitSlot.svelte.d.ts +0 -2
  93. package/dist/svelte/components/Head.svelte +0 -144
  94. package/dist/svelte/components/Head.svelte.d.ts +0 -2
  95. package/dist/svelte/components/Image.svelte +0 -164
  96. package/dist/svelte/components/Image.svelte.d.ts +0 -5
  97. package/dist/svelte/components/Island.svelte +0 -71
  98. package/dist/svelte/components/Island.svelte.d.ts +0 -5
  99. package/dist/svelte/components/JsonLd.svelte +0 -21
  100. package/dist/svelte/components/JsonLd.svelte.d.ts +0 -2
  101. package/dist/svelte/components/StreamSlot.svelte +0 -41
  102. package/dist/svelte/components/StreamSlot.svelte.d.ts +0 -2
  103. package/dist/types/globals.d.ts +0 -121
@@ -1,551 +0,0 @@
1
- import type {} from '../../../types/globals';
2
- /* Angular HMR — Re-Bootstrap with View Transitions API (Zero Flicker)
3
- DEV MODE ONLY — never active in production.
4
-
5
- Strategy:
6
- 1. Capture component state (ng.getComponent) + DOM state
7
- 2. Use document.startViewTransition() — browser captures a screenshot
8
- 3. Destroy old app, recreate root element, import new module
9
- 4. bootstrapApplication() renders new content (behind the screenshot)
10
- 5. After bootstrap: restore state via ng.getComponent + ng.applyChanges
11
- 6. View transition resolves — browser smoothly crossfades to new content
12
-
13
- document.startViewTransition() is the native browser API for page
14
- transitions. It captures a screenshot before the callback, runs the
15
- callback (which can be async), and crossfades when the callback finishes.
16
- The user never sees empty/default state — only the before and after. */
17
-
18
- import { ANGULAR_INIT_TIMEOUT_MS } from '../constants';
19
- import {
20
- saveFormState,
21
- restoreFormState,
22
- saveScrollState,
23
- restoreScrollState
24
- } from '../domState';
25
- import { detectCurrentFramework, findIndexPath } from '../frameworkDetect';
26
-
27
- type HMRMessage = {
28
- data: {
29
- cssBaseName?: string;
30
- cssUrl?: string;
31
- html?: string;
32
- manifest?: Record<string, string>;
33
- pageModuleUrl?: string;
34
- serverDuration?: number;
35
- sourceFile?: string;
36
- updateType?: string;
37
- };
38
- };
39
-
40
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
- type NgApi = any;
42
-
43
- const swapStylesheet = (
44
- cssUrl: string,
45
- cssBaseName: string,
46
- framework: string
47
- ) => {
48
- let existingLink: HTMLLinkElement | null = null;
49
- document.querySelectorAll('link[rel="stylesheet"]').forEach((link) => {
50
- const linkEl = link instanceof HTMLLinkElement ? link : null;
51
- const href = linkEl?.getAttribute('href') ?? '';
52
- if (href.includes(cssBaseName) || href.includes(framework)) {
53
- existingLink = linkEl;
54
- }
55
- });
56
- if (!existingLink) return;
57
-
58
- const capturedExisting: HTMLLinkElement = existingLink;
59
- const newLink = document.createElement('link');
60
- newLink.rel = 'stylesheet';
61
- newLink.href = `${cssUrl}?t=${Date.now()}`;
62
- newLink.onload = function () {
63
- if (capturedExisting && capturedExisting.parentNode)
64
- capturedExisting.remove();
65
- };
66
- document.head.appendChild(newLink);
67
- };
68
-
69
- // ─── State Capture/Restore via ng.getComponent ──────────────
70
-
71
- type StateSnapshot = {
72
- selector: string;
73
- index: number;
74
- properties: Record<string, unknown>;
75
- };
76
-
77
- const readDomCounter = (
78
- element: Element,
79
- properties: Record<string, unknown>
80
- ) => {
81
- element
82
- .querySelectorAll('[class*="value"], [class*="count"]')
83
- .forEach((stateEl) => {
84
- const text = stateEl.textContent;
85
- if (text === null || text.trim() === '') return;
86
- const num = parseInt(text.trim(), 10);
87
- if (!isNaN(num)) properties['__dom_counter'] = num;
88
- });
89
- };
90
-
91
- const copyInstanceProperty = (
92
- instance: Record<string, unknown>,
93
- key: string,
94
- properties: Record<string, unknown>
95
- ) => {
96
- if (key.startsWith('ɵ') || key.startsWith('__')) return;
97
- const val = instance[key];
98
- if (typeof val === 'function') return;
99
- properties[key] = val;
100
- };
101
-
102
- const captureInstanceProperties = (
103
- ngApi: NgApi,
104
- element: Element,
105
- properties: Record<string, unknown>
106
- ) => {
107
- if (!ngApi || typeof ngApi.getComponent !== 'function') return;
108
-
109
- try {
110
- const instance = ngApi.getComponent(element);
111
- if (!instance) return;
112
-
113
- const record: Record<string, unknown> = instance;
114
- Object.keys(record).forEach((key) => {
115
- copyInstanceProperty(record, key, properties);
116
- });
117
- } catch {
118
- /* ignored */
119
- }
120
- };
121
-
122
- const captureComponentState = () => {
123
- const snapshots: StateSnapshot[] = [];
124
- const selectorCounts = new Map<string, number>();
125
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
126
- const ngApi: NgApi = (window as any).ng;
127
-
128
- document.querySelectorAll('*').forEach((elem) => {
129
- const tagName = elem.tagName.toLowerCase();
130
- if (!tagName.includes('-')) return;
131
-
132
- const count = selectorCounts.get(tagName) || 0;
133
- selectorCounts.set(tagName, count + 1);
134
-
135
- const properties: Record<string, unknown> = {};
136
- readDomCounter(elem, properties);
137
- captureInstanceProperties(ngApi, elem, properties);
138
-
139
- if (Object.keys(properties).length > 0) {
140
- snapshots.push({ index: count, properties, selector: tagName });
141
- }
142
- });
143
-
144
- return snapshots;
145
- };
146
-
147
- const safeSetProperty = (
148
- instance: Record<string, unknown>,
149
- key: string,
150
- value: unknown
151
- ) => {
152
- try {
153
- instance[key] = value;
154
- } catch {
155
- /* ignored */
156
- }
157
- };
158
-
159
- const restoreInstanceProperties = (
160
- instance: Record<string, unknown>,
161
- snap: StateSnapshot
162
- ) => {
163
- const domCounter = snap.properties['__dom_counter'];
164
- Object.entries(snap.properties).forEach(([key, value]) => {
165
- if (key === '__dom_counter') return;
166
- safeSetProperty(instance, key, value);
167
- });
168
- if (
169
- domCounter !== undefined &&
170
- typeof domCounter === 'number' &&
171
- 'count' in instance
172
- ) {
173
- instance['count'] = domCounter;
174
- }
175
- };
176
-
177
- const restoreViaInstance = (
178
- ngApi: NgApi,
179
- element: Element,
180
- snap: StateSnapshot
181
- ) => {
182
- if (!ngApi || typeof ngApi.getComponent !== 'function') return false;
183
-
184
- try {
185
- const instance = ngApi.getComponent(element);
186
- if (!instance) return false;
187
-
188
- const record: Record<string, unknown> = instance;
189
- restoreInstanceProperties(record, snap);
190
- if (typeof ngApi.applyChanges === 'function')
191
- ngApi.applyChanges(element);
192
-
193
- return true;
194
- } catch {
195
- return false;
196
- }
197
- };
198
-
199
- const restoreDomFallback = (element: Element, snap: StateSnapshot) => {
200
- const domCounter = snap.properties['__dom_counter'];
201
- if (domCounter === undefined) return;
202
-
203
- element
204
- .querySelectorAll('[class*="value"], [class*="count"]')
205
- .forEach((counterEl) => {
206
- counterEl.textContent = String(domCounter);
207
- });
208
- };
209
-
210
- const restoreComponentState = (snapshots: StateSnapshot[]) => {
211
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
212
- const ngApi: NgApi = (window as any).ng;
213
- if (snapshots.length === 0) return;
214
-
215
- const bySelector = new Map<string, StateSnapshot[]>();
216
- for (const snap of snapshots) {
217
- const list = bySelector.get(snap.selector) || [];
218
- list.push(snap);
219
- bySelector.set(snap.selector, list);
220
- }
221
-
222
- bySelector.forEach((snaps, selector) => {
223
- const elements = document.querySelectorAll(selector);
224
- snaps.forEach((snap) => {
225
- const element = elements[snap.index];
226
- if (!element) return;
227
-
228
- const restored = restoreViaInstance(ngApi, element, snap);
229
- if (!restored) restoreDomFallback(element, snap);
230
- });
231
- });
232
- };
233
-
234
- // ─── Wait for Angular bootstrap (event-based, no polling) ───
235
- // Installs a property setter trap on window.__ANGULAR_APP__ that
236
- // resolves the promise the instant the bootstrap code writes to it.
237
- // Falls back to a short timeout in case the setter is bypassed.
238
-
239
- const waitForAngularApp = () => {
240
- if (window.__ANGULAR_APP__) return Promise.resolve();
241
-
242
- // eslint-disable-next-line promise/avoid-new
243
- return new Promise<void>((resolve) => {
244
- const timeout = setTimeout(resolve, ANGULAR_INIT_TIMEOUT_MS);
245
-
246
- let stored = window.__ANGULAR_APP__;
247
-
248
- Object.defineProperty(window, '__ANGULAR_APP__', {
249
- configurable: true,
250
- enumerable: true,
251
- get() {
252
- return stored;
253
- },
254
- set(val) {
255
- stored = val;
256
- Object.defineProperty(window, '__ANGULAR_APP__', {
257
- configurable: true,
258
- enumerable: true,
259
- value: val,
260
- writable: true
261
- });
262
- clearTimeout(timeout);
263
- resolve();
264
- }
265
- });
266
- });
267
- };
268
-
269
- // ============================================================
270
- // FAST UPDATE — Runtime patching without destroy/re-bootstrap
271
- // ============================================================
272
-
273
- const suppressNg0912 = () => {
274
- const origWarn = console.warn;
275
- console.warn = function (...args: unknown[]) {
276
- if (typeof args[0] === 'string' && args[0].includes('NG0912')) return;
277
- origWarn.apply(console, args);
278
- };
279
-
280
- return origWarn;
281
- };
282
-
283
- const tryPatchExport = (
284
- exportName: string,
285
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
286
- newModule: Record<string, any>,
287
- registry: Map<string, unknown>,
288
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
289
- hmr: any,
290
- sourceFile: string
291
- ) => {
292
- const exported = newModule[exportName];
293
- if (typeof exported !== 'function' || !exported.ɵcmp) return 'skip';
294
-
295
- const registryId = `${sourceFile}#${exportName}`;
296
- if (!registry.has(registryId)) return 'skip';
297
-
298
- const success = hmr.applyUpdate(registryId, exported);
299
- if (!success) return 'fail';
300
-
301
- return 'patched';
302
- };
303
-
304
- const patchRegisteredComponents = (
305
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
306
- newModule: Record<string, any>,
307
- registry: Map<string, unknown>,
308
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
309
- hmr: any,
310
- sourceFile: string
311
- ) => {
312
- let patchedAny = false;
313
- const allPatched = Object.keys(newModule).every((exportName) => {
314
- const result = tryPatchExport(
315
- exportName,
316
- newModule,
317
- registry,
318
- hmr,
319
- sourceFile
320
- );
321
- if (result === 'skip') {
322
- return true;
323
- }
324
- if (result === 'fail') {
325
- return false;
326
- }
327
- patchedAny = true;
328
-
329
- return true;
330
- });
331
-
332
- return { allPatched, patchedAny };
333
- };
334
-
335
- const attemptFastPatch = async (
336
- indexPath: string,
337
- registry: Map<string, unknown>,
338
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
339
- hmr: any,
340
- sourceFile: string,
341
- origWarn: typeof console.warn
342
- ) => {
343
- try {
344
- const newModule = await import(`${indexPath}?t=${Date.now()}`);
345
-
346
- console.warn = origWarn;
347
-
348
- const { allPatched, patchedAny } = patchRegisteredComponents(
349
- newModule,
350
- registry,
351
- hmr,
352
- sourceFile
353
- );
354
-
355
- if (!patchedAny) return false;
356
- if (!allPatched) return false;
357
-
358
- hmr.refresh();
359
-
360
- return true;
361
- } catch (err) {
362
- console.warn = origWarn;
363
- console.warn('[HMR] Angular fast update failed, falling back:', err);
364
-
365
- return false;
366
- }
367
- };
368
-
369
- // handleFastUpdate is kept for future use when the fast path is re-enabled.
370
- const _handleFastUpdate = async (message: HMRMessage) => {
371
- const hmr = window.__ANGULAR_HMR__;
372
- if (!hmr || !hmr.getRegistry) return false;
373
-
374
- const registry = hmr.getRegistry();
375
- if (registry.size === 0) return false;
376
-
377
- const indexPath = findIndexPath(
378
- message.data.manifest,
379
- message.data.sourceFile,
380
- 'angular'
381
- );
382
- if (!indexPath) return false;
383
-
384
- const origWarn = suppressNg0912();
385
-
386
- const patched = await attemptFastPatch(
387
- indexPath,
388
- registry,
389
- hmr,
390
- message.data.sourceFile || '',
391
- origWarn
392
- );
393
-
394
- if (patched && message.data.cssUrl) {
395
- swapStylesheet(
396
- message.data.cssUrl,
397
- message.data.cssBaseName || '',
398
- 'angular'
399
- );
400
- }
401
-
402
- return patched;
403
- };
404
-
405
- // ============================================================
406
- // MAIN ENTRY POINT
407
- // ============================================================
408
-
409
- export const handleAngularUpdate = (message: HMRMessage) => {
410
- if (detectCurrentFramework() !== 'angular') return;
411
-
412
- const updateType = message.data.updateType || 'logic';
413
-
414
- if (
415
- (updateType === 'style' || updateType === 'css-only') &&
416
- message.data.cssUrl
417
- ) {
418
- swapStylesheet(
419
- message.data.cssUrl,
420
- message.data.cssBaseName || '',
421
- 'angular'
422
- );
423
-
424
- return;
425
- }
426
-
427
- handleFullUpdate(message);
428
- };
429
-
430
- // ============================================================
431
- // RE-BOOTSTRAP WITH VIEW TRANSITIONS API
432
- // ============================================================
433
-
434
- const findRootSelector = (container: Element) => {
435
- const candidates = container.querySelectorAll('*');
436
- for (let idx = 0; idx < candidates.length; idx++) {
437
- const candidate = candidates[idx];
438
- if (!candidate) continue;
439
- const tag = candidate.tagName.toLowerCase();
440
- if (tag.includes('-')) return tag;
441
- }
442
-
443
- return null;
444
- };
445
-
446
- const destroyAngularApp = () => {
447
- if (!window.__ANGULAR_APP__) return;
448
-
449
- try {
450
- window.__ANGULAR_APP__.destroy();
451
- } catch {
452
- /* ignored */
453
- }
454
- window.__ANGULAR_APP__ = null;
455
- };
456
-
457
- const bootstrapAngularModule = async (
458
- indexPath: string,
459
- rootSelector: string | null,
460
- rootContainer: Element
461
- ) => {
462
- if (rootSelector && !rootContainer.querySelector(rootSelector)) {
463
- rootContainer.appendChild(document.createElement(rootSelector));
464
- }
465
-
466
- window.__HMR_SKIP_HYDRATION__ = true;
467
-
468
- const origWarn = suppressNg0912();
469
-
470
- await import(`${indexPath}?t=${Date.now()}`);
471
- await waitForAngularApp();
472
-
473
- console.warn = origWarn;
474
- };
475
-
476
- const tickAngularApp = () => {
477
- if (!window.__ANGULAR_APP__) return;
478
-
479
- try {
480
- window.__ANGULAR_APP__.tick();
481
- } catch {
482
- /* ignored */
483
- }
484
- };
485
-
486
- const runWithViewTransition = (updateFn: () => Promise<void>) => {
487
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
488
- const doc = document as any;
489
- if (typeof doc.startViewTransition !== 'function') {
490
- updateFn().catch((err: unknown) => {
491
- console.warn('[HMR] Angular update failed (non-fatal):', err);
492
- });
493
-
494
- return;
495
- }
496
-
497
- let styleEl: HTMLStyleElement | null = null;
498
- try {
499
- styleEl = document.createElement('style');
500
- styleEl.textContent =
501
- '::view-transition-old(root),::view-transition-new(root){animation:none!important}';
502
- document.head.appendChild(styleEl);
503
- } catch {
504
- /* ignored */
505
- }
506
-
507
- const removeStyle = () => {
508
- if (styleEl && styleEl.parentNode) styleEl.remove();
509
- };
510
-
511
- doc.startViewTransition(async () => {
512
- await updateFn();
513
- })
514
- .finished.then(removeStyle)
515
- .catch(removeStyle);
516
- };
517
-
518
- const handleFullUpdate = (message: HMRMessage) => {
519
- const componentState = captureComponentState();
520
- const scrollState = saveScrollState();
521
- const formState = saveFormState();
522
-
523
- if (message.data.cssUrl) {
524
- swapStylesheet(
525
- message.data.cssUrl,
526
- message.data.cssBaseName || '',
527
- 'angular'
528
- );
529
- }
530
-
531
- const rootContainer = document.getElementById('root') || document.body;
532
- const rootSelector = findRootSelector(rootContainer);
533
-
534
- const indexPath = findIndexPath(
535
- message.data.manifest,
536
- message.data.sourceFile,
537
- 'angular'
538
- );
539
- if (!indexPath) return;
540
-
541
- const doUpdate = async () => {
542
- destroyAngularApp();
543
- await bootstrapAngularModule(indexPath, rootSelector, rootContainer);
544
- restoreComponentState(componentState);
545
- tickAngularApp();
546
- restoreFormState(formState);
547
- restoreScrollState(scrollState);
548
- };
549
-
550
- runWithViewTransition(doUpdate);
551
- };