@inertiajs/core 2.3.17 → 3.0.0-beta.1

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.
package/dist/index.esm.js DELETED
@@ -1,4119 +0,0 @@
1
- // src/router.ts
2
- import { cloneDeep as cloneDeep3, get as get3, set as set3 } from "lodash-es";
3
-
4
- // src/config.ts
5
- import { get, has, set } from "lodash-es";
6
- var Config = class {
7
- constructor(defaults) {
8
- this.config = {};
9
- this.defaults = defaults;
10
- }
11
- extend(defaults) {
12
- if (defaults) {
13
- this.defaults = { ...this.defaults, ...defaults };
14
- }
15
- return this;
16
- }
17
- replace(newConfig) {
18
- this.config = newConfig;
19
- }
20
- get(key) {
21
- return has(this.config, key) ? get(this.config, key) : get(this.defaults, key);
22
- }
23
- set(keyOrValues, value) {
24
- if (typeof keyOrValues === "string") {
25
- set(this.config, keyOrValues, value);
26
- } else {
27
- Object.entries(keyOrValues).forEach(([key, val]) => {
28
- set(this.config, key, val);
29
- });
30
- }
31
- }
32
- };
33
- var config = new Config({
34
- form: {
35
- recentlySuccessfulDuration: 2e3,
36
- forceIndicesArrayFormatInFormData: true,
37
- withAllErrors: false
38
- },
39
- future: {
40
- preserveEqualProps: false,
41
- useDataInertiaHeadAttribute: false,
42
- useDialogForErrorModal: false,
43
- useScriptElementForInitialPage: false
44
- },
45
- prefetch: {
46
- cacheFor: 3e4,
47
- hoverDelay: 75
48
- }
49
- });
50
-
51
- // src/debounce.ts
52
- function debounce(fn, delay) {
53
- let timeoutID;
54
- return function(...args) {
55
- clearTimeout(timeoutID);
56
- timeoutID = setTimeout(() => fn.apply(this, args), delay);
57
- };
58
- }
59
-
60
- // src/events.ts
61
- function fireEvent(name, options) {
62
- return document.dispatchEvent(new CustomEvent(`inertia:${name}`, options));
63
- }
64
- var fireBeforeEvent = (visit) => {
65
- return fireEvent("before", { cancelable: true, detail: { visit } });
66
- };
67
- var fireErrorEvent = (errors) => {
68
- return fireEvent("error", { detail: { errors } });
69
- };
70
- var fireExceptionEvent = (exception) => {
71
- return fireEvent("exception", { cancelable: true, detail: { exception } });
72
- };
73
- var fireFinishEvent = (visit) => {
74
- return fireEvent("finish", { detail: { visit } });
75
- };
76
- var fireInvalidEvent = (response) => {
77
- return fireEvent("invalid", { cancelable: true, detail: { response } });
78
- };
79
- var fireBeforeUpdateEvent = (page2) => {
80
- return fireEvent("beforeUpdate", { detail: { page: page2 } });
81
- };
82
- var fireNavigateEvent = (page2) => {
83
- return fireEvent("navigate", { detail: { page: page2 } });
84
- };
85
- var fireProgressEvent = (progress3) => {
86
- return fireEvent("progress", { detail: { progress: progress3 } });
87
- };
88
- var fireStartEvent = (visit) => {
89
- return fireEvent("start", { detail: { visit } });
90
- };
91
- var fireSuccessEvent = (page2) => {
92
- return fireEvent("success", { detail: { page: page2 } });
93
- };
94
- var firePrefetchedEvent = (response, visit) => {
95
- return fireEvent("prefetched", { detail: { fetchedAt: Date.now(), response: response.data, visit } });
96
- };
97
- var firePrefetchingEvent = (visit) => {
98
- return fireEvent("prefetching", { detail: { visit } });
99
- };
100
- var fireFlashEvent = (flash) => {
101
- return fireEvent("flash", { detail: { flash } });
102
- };
103
-
104
- // src/history.ts
105
- import { cloneDeep as cloneDeep2, isEqual } from "lodash-es";
106
-
107
- // src/sessionStorage.ts
108
- var SessionStorage = class {
109
- static set(key, value) {
110
- if (typeof window !== "undefined") {
111
- window.sessionStorage.setItem(key, JSON.stringify(value));
112
- }
113
- }
114
- static get(key) {
115
- if (typeof window !== "undefined") {
116
- return JSON.parse(window.sessionStorage.getItem(key) || "null");
117
- }
118
- }
119
- static merge(key, value) {
120
- const existing = this.get(key);
121
- if (existing === null) {
122
- this.set(key, value);
123
- } else {
124
- this.set(key, { ...existing, ...value });
125
- }
126
- }
127
- static remove(key) {
128
- if (typeof window !== "undefined") {
129
- window.sessionStorage.removeItem(key);
130
- }
131
- }
132
- static removeNested(key, nestedKey) {
133
- const existing = this.get(key);
134
- if (existing !== null) {
135
- delete existing[nestedKey];
136
- this.set(key, existing);
137
- }
138
- }
139
- static exists(key) {
140
- try {
141
- return this.get(key) !== null;
142
- } catch (error) {
143
- return false;
144
- }
145
- }
146
- static clear() {
147
- if (typeof window !== "undefined") {
148
- window.sessionStorage.clear();
149
- }
150
- }
151
- };
152
- SessionStorage.locationVisitKey = "inertiaLocationVisit";
153
-
154
- // src/encryption.ts
155
- var encryptHistory = async (data) => {
156
- if (typeof window === "undefined") {
157
- throw new Error("Unable to encrypt history");
158
- }
159
- const iv = getIv();
160
- const storedKey = await getKeyFromSessionStorage();
161
- const key = await getOrCreateKey(storedKey);
162
- if (!key) {
163
- throw new Error("Unable to encrypt history");
164
- }
165
- const encrypted = await encryptData(iv, key, data);
166
- return encrypted;
167
- };
168
- var historySessionStorageKeys = {
169
- key: "historyKey",
170
- iv: "historyIv"
171
- };
172
- var decryptHistory = async (data) => {
173
- const iv = getIv();
174
- const storedKey = await getKeyFromSessionStorage();
175
- if (!storedKey) {
176
- throw new Error("Unable to decrypt history");
177
- }
178
- return await decryptData(iv, storedKey, data);
179
- };
180
- var encryptData = async (iv, key, data) => {
181
- if (typeof window === "undefined") {
182
- throw new Error("Unable to encrypt history");
183
- }
184
- if (typeof window.crypto.subtle === "undefined") {
185
- console.warn("Encryption is not supported in this environment. SSL is required.");
186
- return Promise.resolve(data);
187
- }
188
- const textEncoder = new TextEncoder();
189
- const str = JSON.stringify(data);
190
- const encoded = new Uint8Array(str.length * 3);
191
- const result = textEncoder.encodeInto(str, encoded);
192
- return window.crypto.subtle.encrypt(
193
- {
194
- name: "AES-GCM",
195
- iv
196
- },
197
- key,
198
- encoded.subarray(0, result.written)
199
- );
200
- };
201
- var decryptData = async (iv, key, data) => {
202
- if (typeof window.crypto.subtle === "undefined") {
203
- console.warn("Decryption is not supported in this environment. SSL is required.");
204
- return Promise.resolve(data);
205
- }
206
- const decrypted = await window.crypto.subtle.decrypt(
207
- {
208
- name: "AES-GCM",
209
- iv
210
- },
211
- key,
212
- data
213
- );
214
- return JSON.parse(new TextDecoder().decode(decrypted));
215
- };
216
- var getIv = () => {
217
- const ivString = SessionStorage.get(historySessionStorageKeys.iv);
218
- if (ivString) {
219
- return new Uint8Array(ivString);
220
- }
221
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
222
- SessionStorage.set(historySessionStorageKeys.iv, Array.from(iv));
223
- return iv;
224
- };
225
- var createKey = async () => {
226
- if (typeof window.crypto.subtle === "undefined") {
227
- console.warn("Encryption is not supported in this environment. SSL is required.");
228
- return Promise.resolve(null);
229
- }
230
- return window.crypto.subtle.generateKey(
231
- {
232
- name: "AES-GCM",
233
- length: 256
234
- },
235
- true,
236
- ["encrypt", "decrypt"]
237
- );
238
- };
239
- var saveKey = async (key) => {
240
- if (typeof window.crypto.subtle === "undefined") {
241
- console.warn("Encryption is not supported in this environment. SSL is required.");
242
- return Promise.resolve();
243
- }
244
- const keyData = await window.crypto.subtle.exportKey("raw", key);
245
- SessionStorage.set(historySessionStorageKeys.key, Array.from(new Uint8Array(keyData)));
246
- };
247
- var getOrCreateKey = async (key) => {
248
- if (key) {
249
- return key;
250
- }
251
- const newKey = await createKey();
252
- if (!newKey) {
253
- return null;
254
- }
255
- await saveKey(newKey);
256
- return newKey;
257
- };
258
- var getKeyFromSessionStorage = async () => {
259
- const stringKey = SessionStorage.get(historySessionStorageKeys.key);
260
- if (!stringKey) {
261
- return null;
262
- }
263
- const key = await window.crypto.subtle.importKey(
264
- "raw",
265
- new Uint8Array(stringKey),
266
- {
267
- name: "AES-GCM",
268
- length: 256
269
- },
270
- true,
271
- ["encrypt", "decrypt"]
272
- );
273
- return key;
274
- };
275
-
276
- // src/prefetched.ts
277
- import { cloneDeep } from "lodash-es";
278
-
279
- // src/objectUtils.ts
280
- var objectsAreEqual = (obj1, obj2, excludeKeys) => {
281
- if (obj1 === obj2) {
282
- return true;
283
- }
284
- for (const key in obj1) {
285
- if (excludeKeys.includes(key)) {
286
- continue;
287
- }
288
- if (obj1[key] === obj2[key]) {
289
- continue;
290
- }
291
- if (!compareValues(obj1[key], obj2[key])) {
292
- return false;
293
- }
294
- }
295
- for (const key in obj2) {
296
- if (excludeKeys.includes(key)) {
297
- continue;
298
- }
299
- if (!(key in obj1)) {
300
- return false;
301
- }
302
- }
303
- return true;
304
- };
305
- var compareValues = (value1, value2) => {
306
- switch (typeof value1) {
307
- case "object":
308
- return objectsAreEqual(value1, value2, []);
309
- case "function":
310
- return value1.toString() === value2.toString();
311
- default:
312
- return value1 === value2;
313
- }
314
- };
315
-
316
- // src/time.ts
317
- var conversionMap = {
318
- ms: 1,
319
- s: 1e3,
320
- m: 1e3 * 60,
321
- h: 1e3 * 60 * 60,
322
- d: 1e3 * 60 * 60 * 24
323
- };
324
- var timeToMs = (time) => {
325
- if (typeof time === "number") {
326
- return time;
327
- }
328
- for (const [unit, conversion] of Object.entries(conversionMap)) {
329
- if (time.endsWith(unit)) {
330
- return parseFloat(time) * conversion;
331
- }
332
- }
333
- return parseInt(time);
334
- };
335
-
336
- // src/prefetched.ts
337
- var PrefetchedRequests = class {
338
- constructor() {
339
- this.cached = [];
340
- this.inFlightRequests = [];
341
- this.removalTimers = [];
342
- this.currentUseId = null;
343
- }
344
- add(params, sendFunc, { cacheFor, cacheTags }) {
345
- const inFlight = this.findInFlight(params);
346
- if (inFlight) {
347
- return Promise.resolve();
348
- }
349
- const existing = this.findCached(params);
350
- if (!params.fresh && existing && existing.staleTimestamp > Date.now()) {
351
- return Promise.resolve();
352
- }
353
- const [stale, prefetchExpiresIn] = this.extractStaleValues(cacheFor);
354
- const promise = new Promise((resolve, reject) => {
355
- sendFunc({
356
- ...params,
357
- onCancel: () => {
358
- this.remove(params);
359
- params.onCancel();
360
- reject();
361
- },
362
- onError: (error) => {
363
- this.remove(params);
364
- params.onError(error);
365
- reject();
366
- },
367
- onPrefetching(visitParams) {
368
- params.onPrefetching(visitParams);
369
- },
370
- onPrefetched(response, visit) {
371
- params.onPrefetched(response, visit);
372
- },
373
- onPrefetchResponse(response) {
374
- resolve(response);
375
- },
376
- onPrefetchError(error) {
377
- prefetchedRequests.removeFromInFlight(params);
378
- reject(error);
379
- }
380
- });
381
- }).then((response) => {
382
- this.remove(params);
383
- const pageResponse = response.getPageResponse();
384
- page.mergeOncePropsIntoResponse(pageResponse);
385
- this.cached.push({
386
- params: { ...params },
387
- staleTimestamp: Date.now() + stale,
388
- expiresAt: Date.now() + prefetchExpiresIn,
389
- response: promise,
390
- singleUse: prefetchExpiresIn === 0,
391
- timestamp: Date.now(),
392
- inFlight: false,
393
- tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags]
394
- });
395
- const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse);
396
- this.scheduleForRemoval(
397
- params,
398
- oncePropExpiresIn ? Math.min(prefetchExpiresIn, oncePropExpiresIn) : prefetchExpiresIn
399
- );
400
- this.removeFromInFlight(params);
401
- response.handlePrefetch();
402
- return response;
403
- });
404
- this.inFlightRequests.push({
405
- params: { ...params },
406
- response: promise,
407
- staleTimestamp: null,
408
- inFlight: true
409
- });
410
- return promise;
411
- }
412
- removeAll() {
413
- this.cached = [];
414
- this.removalTimers.forEach((removalTimer) => {
415
- clearTimeout(removalTimer.timer);
416
- });
417
- this.removalTimers = [];
418
- }
419
- removeByTags(tags) {
420
- this.cached = this.cached.filter((prefetched) => {
421
- return !prefetched.tags.some((tag) => tags.includes(tag));
422
- });
423
- }
424
- remove(params) {
425
- this.cached = this.cached.filter((prefetched) => {
426
- return !this.paramsAreEqual(prefetched.params, params);
427
- });
428
- this.clearTimer(params);
429
- }
430
- removeFromInFlight(params) {
431
- this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
432
- return !this.paramsAreEqual(prefetching.params, params);
433
- });
434
- }
435
- extractStaleValues(cacheFor) {
436
- const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor);
437
- return [timeToMs(stale), timeToMs(expires)];
438
- }
439
- cacheForToStaleAndExpires(cacheFor) {
440
- if (!Array.isArray(cacheFor)) {
441
- return [cacheFor, cacheFor];
442
- }
443
- switch (cacheFor.length) {
444
- case 0:
445
- return [0, 0];
446
- case 1:
447
- return [cacheFor[0], cacheFor[0]];
448
- default:
449
- return [cacheFor[0], cacheFor[1]];
450
- }
451
- }
452
- clearTimer(params) {
453
- const timer = this.removalTimers.find((removalTimer) => {
454
- return this.paramsAreEqual(removalTimer.params, params);
455
- });
456
- if (timer) {
457
- clearTimeout(timer.timer);
458
- this.removalTimers = this.removalTimers.filter((removalTimer) => removalTimer !== timer);
459
- }
460
- }
461
- scheduleForRemoval(params, expiresIn) {
462
- if (typeof window === "undefined") {
463
- return;
464
- }
465
- this.clearTimer(params);
466
- if (expiresIn > 0) {
467
- const timer = window.setTimeout(() => this.remove(params), expiresIn);
468
- this.removalTimers.push({
469
- params,
470
- timer
471
- });
472
- }
473
- }
474
- get(params) {
475
- return this.findCached(params) || this.findInFlight(params);
476
- }
477
- use(prefetched, params) {
478
- const id = `${params.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
479
- this.currentUseId = id;
480
- return prefetched.response.then((response) => {
481
- if (this.currentUseId !== id) {
482
- return;
483
- }
484
- response.mergeParams({ ...params, onPrefetched: () => {
485
- } });
486
- this.removeSingleUseItems(params);
487
- return response.handle();
488
- });
489
- }
490
- removeSingleUseItems(params) {
491
- this.cached = this.cached.filter((prefetched) => {
492
- if (!this.paramsAreEqual(prefetched.params, params)) {
493
- return true;
494
- }
495
- return !prefetched.singleUse;
496
- });
497
- }
498
- findCached(params) {
499
- return this.cached.find((prefetched) => {
500
- return this.paramsAreEqual(prefetched.params, params);
501
- }) || null;
502
- }
503
- findInFlight(params) {
504
- return this.inFlightRequests.find((prefetched) => {
505
- return this.paramsAreEqual(prefetched.params, params);
506
- }) || null;
507
- }
508
- withoutPurposePrefetchHeader(params) {
509
- const newParams = cloneDeep(params);
510
- if (newParams.headers["Purpose"] === "prefetch") {
511
- delete newParams.headers["Purpose"];
512
- }
513
- return newParams;
514
- }
515
- paramsAreEqual(params1, params2) {
516
- return objectsAreEqual(
517
- this.withoutPurposePrefetchHeader(params1),
518
- this.withoutPurposePrefetchHeader(params2),
519
- [
520
- "showProgress",
521
- "replace",
522
- "prefetch",
523
- "preserveScroll",
524
- "preserveState",
525
- "onBefore",
526
- "onBeforeUpdate",
527
- "onStart",
528
- "onProgress",
529
- "onFinish",
530
- "onCancel",
531
- "onSuccess",
532
- "onError",
533
- "onFlash",
534
- "onPrefetched",
535
- "onCancelToken",
536
- "onPrefetching",
537
- "async",
538
- "viewTransition"
539
- ]
540
- );
541
- }
542
- updateCachedOncePropsFromCurrentPage() {
543
- this.cached.forEach((prefetched) => {
544
- prefetched.response.then((response) => {
545
- const pageResponse = response.getPageResponse();
546
- page.mergeOncePropsIntoResponse(pageResponse, { force: true });
547
- for (const [group, deferredProps] of Object.entries(pageResponse.deferredProps ?? {})) {
548
- const remaining = deferredProps.filter((prop) => pageResponse.props[prop] === void 0);
549
- if (remaining.length > 0) {
550
- pageResponse.deferredProps[group] = remaining;
551
- } else {
552
- delete pageResponse.deferredProps[group];
553
- }
554
- }
555
- const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse);
556
- if (oncePropExpiresIn === null) {
557
- return;
558
- }
559
- const prefetchExpiresIn = prefetched.expiresAt - Date.now();
560
- const expiresIn = Math.min(prefetchExpiresIn, oncePropExpiresIn);
561
- if (expiresIn > 0) {
562
- this.scheduleForRemoval(prefetched.params, expiresIn);
563
- } else {
564
- this.remove(prefetched.params);
565
- }
566
- });
567
- });
568
- }
569
- getShortestOncePropTtl(page2) {
570
- const expiryTimestamps = Object.values(page2.onceProps ?? {}).map((onceProp) => onceProp.expiresAt).filter((expiresAt) => !!expiresAt);
571
- if (expiryTimestamps.length === 0) {
572
- return null;
573
- }
574
- return Math.min(...expiryTimestamps) - Date.now();
575
- }
576
- };
577
- var prefetchedRequests = new PrefetchedRequests();
578
-
579
- // src/domUtils.ts
580
- var elementInViewport = (el) => {
581
- if (el.offsetParent === null) {
582
- return false;
583
- }
584
- const rect = el.getBoundingClientRect();
585
- const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0;
586
- const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0;
587
- return verticallyVisible && horizontallyVisible;
588
- };
589
- var getScrollableParent = (element) => {
590
- const allowsVerticalScroll = (el) => {
591
- const computedStyle = window.getComputedStyle(el);
592
- if (["scroll", "overlay"].includes(computedStyle.overflowY)) {
593
- return true;
594
- }
595
- if (computedStyle.overflowY !== "auto") {
596
- return false;
597
- }
598
- if (["visible", "clip"].includes(computedStyle.overflowX)) {
599
- return true;
600
- }
601
- return hasDimensionConstraint(computedStyle.maxHeight, el.style.height) || isConstrainedByLayout(el, "height");
602
- };
603
- const allowsHorizontalScroll = (el) => {
604
- const computedStyle = window.getComputedStyle(el);
605
- if (["scroll", "overlay"].includes(computedStyle.overflowX)) {
606
- return true;
607
- }
608
- if (computedStyle.overflowX !== "auto") {
609
- return false;
610
- }
611
- if (["visible", "clip"].includes(computedStyle.overflowY)) {
612
- return true;
613
- }
614
- return hasDimensionConstraint(computedStyle.maxWidth, el.style.width) || isConstrainedByLayout(el, "width");
615
- };
616
- const hasDimensionConstraint = (computedMaxDimension, inlineStyleDimension) => {
617
- if (computedMaxDimension && computedMaxDimension !== "none" && computedMaxDimension !== "0px") {
618
- return true;
619
- }
620
- if (inlineStyleDimension && inlineStyleDimension !== "auto" && inlineStyleDimension !== "0") {
621
- return true;
622
- }
623
- return false;
624
- };
625
- const isConstrainedByLayout = (el, dimension) => {
626
- const parent2 = el.parentElement;
627
- if (!parent2) {
628
- return false;
629
- }
630
- const parentStyle = window.getComputedStyle(parent2);
631
- if (["flex", "inline-flex"].includes(parentStyle.display)) {
632
- const isColumnLayout = ["column", "column-reverse"].includes(parentStyle.flexDirection);
633
- return dimension === "height" ? isColumnLayout : !isColumnLayout;
634
- }
635
- return ["grid", "inline-grid"].includes(parentStyle.display);
636
- };
637
- let parent = element?.parentElement;
638
- while (parent) {
639
- const allowsScroll = allowsVerticalScroll(parent) || allowsHorizontalScroll(parent);
640
- if (window.getComputedStyle(parent).display !== "contents" && allowsScroll) {
641
- return parent;
642
- }
643
- parent = parent.parentElement;
644
- }
645
- return null;
646
- };
647
- var getElementsInViewportFromCollection = (elements, referenceElement) => {
648
- if (!referenceElement) {
649
- return elements.filter((element) => elementInViewport(element));
650
- }
651
- const referenceIndex = elements.indexOf(referenceElement);
652
- const upwardElements = [];
653
- const downwardElements = [];
654
- for (let i = referenceIndex; i >= 0; i--) {
655
- const element = elements[i];
656
- if (elementInViewport(element)) {
657
- upwardElements.push(element);
658
- } else {
659
- break;
660
- }
661
- }
662
- for (let i = referenceIndex + 1; i < elements.length; i++) {
663
- const element = elements[i];
664
- if (elementInViewport(element)) {
665
- downwardElements.push(element);
666
- } else {
667
- break;
668
- }
669
- }
670
- return [...upwardElements.reverse(), ...downwardElements];
671
- };
672
- var requestAnimationFrame = (cb, times = 1) => {
673
- window.requestAnimationFrame(() => {
674
- if (times > 1) {
675
- requestAnimationFrame(cb, times - 1);
676
- } else {
677
- cb();
678
- }
679
- });
680
- };
681
- var getInitialPageFromDOM = (id, useScriptElement = false) => {
682
- if (typeof window === "undefined") {
683
- return null;
684
- }
685
- if (!useScriptElement) {
686
- const el = document.getElementById(id);
687
- if (el?.dataset.page) {
688
- return JSON.parse(el.dataset.page);
689
- }
690
- }
691
- const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`);
692
- if (scriptEl?.textContent) {
693
- return JSON.parse(scriptEl.textContent);
694
- }
695
- return null;
696
- };
697
-
698
- // src/scroll.ts
699
- var isServer = typeof window === "undefined";
700
- var isFirefox = !isServer && /Firefox/i.test(window.navigator.userAgent);
701
- var Scroll = class {
702
- static save() {
703
- history.saveScrollPositions(this.getScrollRegions());
704
- }
705
- static getScrollRegions() {
706
- return Array.from(this.regions()).map((region) => ({
707
- top: region.scrollTop,
708
- left: region.scrollLeft
709
- }));
710
- }
711
- static regions() {
712
- return document.querySelectorAll("[scroll-region]");
713
- }
714
- static scrollToTop() {
715
- if (isFirefox && getComputedStyle(document.documentElement).scrollBehavior === "smooth") {
716
- return requestAnimationFrame(() => window.scrollTo(0, 0), 2);
717
- }
718
- window.scrollTo(0, 0);
719
- }
720
- static reset() {
721
- const anchorHash = isServer ? null : window.location.hash;
722
- if (!anchorHash) {
723
- this.scrollToTop();
724
- }
725
- this.regions().forEach((region) => {
726
- if (typeof region.scrollTo === "function") {
727
- region.scrollTo(0, 0);
728
- } else {
729
- region.scrollTop = 0;
730
- region.scrollLeft = 0;
731
- }
732
- });
733
- this.save();
734
- this.scrollToAnchor();
735
- }
736
- static scrollToAnchor() {
737
- const anchorHash = isServer ? null : window.location.hash;
738
- if (anchorHash) {
739
- setTimeout(() => {
740
- const anchorElement = document.getElementById(anchorHash.slice(1));
741
- anchorElement ? anchorElement.scrollIntoView() : this.scrollToTop();
742
- });
743
- }
744
- }
745
- static restore(scrollRegions) {
746
- if (isServer) {
747
- return;
748
- }
749
- window.requestAnimationFrame(() => {
750
- this.restoreDocument();
751
- this.restoreScrollRegions(scrollRegions);
752
- });
753
- }
754
- static restoreScrollRegions(scrollRegions) {
755
- if (isServer) {
756
- return;
757
- }
758
- this.regions().forEach((region, index) => {
759
- const scrollPosition = scrollRegions[index];
760
- if (!scrollPosition) {
761
- return;
762
- }
763
- if (typeof region.scrollTo === "function") {
764
- region.scrollTo(scrollPosition.left, scrollPosition.top);
765
- } else {
766
- region.scrollTop = scrollPosition.top;
767
- region.scrollLeft = scrollPosition.left;
768
- }
769
- });
770
- }
771
- static restoreDocument() {
772
- const scrollPosition = history.getDocumentScrollPosition();
773
- window.scrollTo(scrollPosition.left, scrollPosition.top);
774
- }
775
- static onScroll(event) {
776
- const target = event.target;
777
- if (typeof target.hasAttribute === "function" && target.hasAttribute("scroll-region")) {
778
- this.save();
779
- }
780
- }
781
- static onWindowScroll() {
782
- history.saveDocumentScrollPosition({
783
- top: window.scrollY,
784
- left: window.scrollX
785
- });
786
- }
787
- };
788
-
789
- // src/url.ts
790
- import * as qs from "qs";
791
-
792
- // src/files.ts
793
- var isFile = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0;
794
- function hasFiles(data) {
795
- return isFile(data) || data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value)) || typeof data === "object" && data !== null && Object.values(data).some((value) => hasFiles(value));
796
- }
797
-
798
- // src/formData.ts
799
- var isFormData = (value) => value instanceof FormData;
800
- function objectToFormData(source, form = new FormData(), parentKey = null, queryStringArrayFormat = "brackets") {
801
- source = source || {};
802
- for (const key in source) {
803
- if (Object.prototype.hasOwnProperty.call(source, key)) {
804
- append(form, composeKey(parentKey, key, "indices"), source[key], queryStringArrayFormat);
805
- }
806
- }
807
- return form;
808
- }
809
- function composeKey(parent, key, format) {
810
- if (!parent) {
811
- return key;
812
- }
813
- return format === "brackets" ? `${parent}[]` : `${parent}[${key}]`;
814
- }
815
- function append(form, key, value, format) {
816
- if (Array.isArray(value)) {
817
- return Array.from(value.keys()).forEach(
818
- (index) => append(form, composeKey(key, index.toString(), format), value[index], format)
819
- );
820
- } else if (value instanceof Date) {
821
- return form.append(key, value.toISOString());
822
- } else if (value instanceof File) {
823
- return form.append(key, value, value.name);
824
- } else if (value instanceof Blob) {
825
- return form.append(key, value);
826
- } else if (typeof value === "boolean") {
827
- return form.append(key, value ? "1" : "0");
828
- } else if (typeof value === "string") {
829
- return form.append(key, value);
830
- } else if (typeof value === "number") {
831
- return form.append(key, `${value}`);
832
- } else if (value === null || value === void 0) {
833
- return form.append(key, "");
834
- }
835
- objectToFormData(value, form, key, format);
836
- }
837
-
838
- // src/url.ts
839
- function hrefToUrl(href) {
840
- return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString());
841
- }
842
- var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFormat) => {
843
- let url = typeof href === "string" ? hrefToUrl(href) : href;
844
- if ((hasFiles(data) || forceFormData) && !isFormData(data)) {
845
- if (config.get("form.forceIndicesArrayFormatInFormData")) {
846
- queryStringArrayFormat = "indices";
847
- }
848
- data = objectToFormData(data, new FormData(), null, queryStringArrayFormat);
849
- }
850
- if (isFormData(data)) {
851
- return [url, data];
852
- }
853
- const [_href, _data] = mergeDataIntoQueryString(method, url, data, queryStringArrayFormat);
854
- return [hrefToUrl(_href), _data];
855
- };
856
- function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") {
857
- const hasDataForQueryString = method === "get" && !isFormData(data) && Object.keys(data).length > 0;
858
- const hasHost = urlHasProtocol(href.toString());
859
- const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === "";
860
- const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?");
861
- const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString());
862
- const hasSearch = href.toString().includes("?") || hasDataForQueryString;
863
- const hasHash = href.toString().includes("#");
864
- const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString());
865
- if (hasDataForQueryString) {
866
- const hasIndices = /\[\d+\]/.test(decodeURIComponent(url.search));
867
- const parseOptions = { ignoreQueryPrefix: true, allowSparse: true };
868
- url.search = qs.stringify(
869
- { ...qs.parse(url.search, parseOptions), ...data },
870
- {
871
- encodeValuesOnly: true,
872
- arrayFormat: hasIndices ? "indices" : qsArrayFormat
873
- }
874
- );
875
- }
876
- return [
877
- [
878
- hasHost ? `${url.protocol}//${url.host}` : "",
879
- hasAbsolutePath ? url.pathname : "",
880
- hasRelativePath ? url.pathname.substring(hasRelativePathWithDotPrefix ? 0 : 1) : "",
881
- hasSearch ? url.search : "",
882
- hasHash ? url.hash : ""
883
- ].join(""),
884
- hasDataForQueryString ? {} : data
885
- ];
886
- }
887
- function urlWithoutHash(url) {
888
- url = new URL(url.href);
889
- url.hash = "";
890
- return url;
891
- }
892
- var setHashIfSameUrl = (originUrl, destinationUrl) => {
893
- if (originUrl.hash && !destinationUrl.hash && urlWithoutHash(originUrl).href === destinationUrl.href) {
894
- destinationUrl.hash = originUrl.hash;
895
- }
896
- };
897
- var isSameUrlWithoutHash = (url1, url2) => {
898
- return urlWithoutHash(url1).href === urlWithoutHash(url2).href;
899
- };
900
- var isSameUrlWithoutQueryOrHash = (url1, url2) => {
901
- return url1.origin === url2.origin && url1.pathname === url2.pathname;
902
- };
903
- function isUrlMethodPair(href) {
904
- return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href;
905
- }
906
- function urlHasProtocol(url) {
907
- return /^([a-z][a-z0-9+.-]*:)?\/\/[^/]/i.test(url);
908
- }
909
- function urlToString(url, absolute) {
910
- const urlObj = typeof url === "string" ? hrefToUrl(url) : url;
911
- return absolute ? `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}${urlObj.search}${urlObj.hash}` : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;
912
- }
913
-
914
- // src/page.ts
915
- var CurrentPage = class {
916
- constructor() {
917
- this.componentId = {};
918
- this.listeners = [];
919
- this.isFirstPageLoad = true;
920
- this.cleared = false;
921
- this.pendingDeferredProps = null;
922
- this.historyQuotaExceeded = false;
923
- }
924
- init({
925
- initialPage,
926
- swapComponent,
927
- resolveComponent,
928
- onFlash
929
- }) {
930
- this.page = { ...initialPage, flash: initialPage.flash ?? {} };
931
- this.swapComponent = swapComponent;
932
- this.resolveComponent = resolveComponent;
933
- this.onFlashCallback = onFlash;
934
- eventHandler.on("historyQuotaExceeded", () => {
935
- this.historyQuotaExceeded = true;
936
- });
937
- return this;
938
- }
939
- set(page2, {
940
- replace = false,
941
- preserveScroll = false,
942
- preserveState = false,
943
- viewTransition = false
944
- } = {}) {
945
- if (Object.keys(page2.deferredProps || {}).length) {
946
- this.pendingDeferredProps = {
947
- deferredProps: page2.deferredProps,
948
- component: page2.component,
949
- url: page2.url
950
- };
951
- if (page2.initialDeferredProps === void 0) {
952
- page2.initialDeferredProps = page2.deferredProps;
953
- }
954
- }
955
- this.componentId = {};
956
- const componentId = this.componentId;
957
- if (page2.clearHistory) {
958
- history.clear();
959
- }
960
- return this.resolve(page2.component).then((component) => {
961
- if (componentId !== this.componentId) {
962
- return;
963
- }
964
- page2.rememberedState ?? (page2.rememberedState = {});
965
- const isServer3 = typeof window === "undefined";
966
- const location = !isServer3 ? window.location : new URL(page2.url);
967
- const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : [];
968
- replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location);
969
- const pageForHistory = { ...page2, flash: {} };
970
- return new Promise(
971
- (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve)
972
- ).then(() => {
973
- const isNewComponent = !this.isTheSame(page2);
974
- if (!isNewComponent && Object.keys(page2.props.errors || {}).length > 0) {
975
- viewTransition = false;
976
- }
977
- this.page = page2;
978
- this.cleared = false;
979
- if (this.hasOnceProps()) {
980
- prefetchedRequests.updateCachedOncePropsFromCurrentPage();
981
- }
982
- if (isNewComponent) {
983
- this.fireEventsFor("newComponent");
984
- }
985
- if (this.isFirstPageLoad) {
986
- this.fireEventsFor("firstLoad");
987
- }
988
- this.isFirstPageLoad = false;
989
- if (this.historyQuotaExceeded) {
990
- this.historyQuotaExceeded = false;
991
- return;
992
- }
993
- return this.swap({
994
- component,
995
- page: page2,
996
- preserveState,
997
- viewTransition
998
- }).then(() => {
999
- if (preserveScroll) {
1000
- window.requestAnimationFrame(() => Scroll.restoreScrollRegions(scrollRegions));
1001
- } else {
1002
- Scroll.reset();
1003
- }
1004
- if (this.pendingDeferredProps && this.pendingDeferredProps.component === page2.component && this.pendingDeferredProps.url === page2.url) {
1005
- eventHandler.fireInternalEvent("loadDeferredProps", this.pendingDeferredProps.deferredProps);
1006
- }
1007
- this.pendingDeferredProps = null;
1008
- if (!replace) {
1009
- fireNavigateEvent(page2);
1010
- }
1011
- });
1012
- });
1013
- });
1014
- }
1015
- setQuietly(page2, {
1016
- preserveState = false
1017
- } = {}) {
1018
- return this.resolve(page2.component).then((component) => {
1019
- this.page = page2;
1020
- this.cleared = false;
1021
- history.setCurrent(page2);
1022
- return this.swap({ component, page: page2, preserveState, viewTransition: false });
1023
- });
1024
- }
1025
- clear() {
1026
- this.cleared = true;
1027
- }
1028
- isCleared() {
1029
- return this.cleared;
1030
- }
1031
- get() {
1032
- return this.page;
1033
- }
1034
- getWithoutFlashData() {
1035
- return { ...this.page, flash: {} };
1036
- }
1037
- hasOnceProps() {
1038
- return Object.keys(this.page.onceProps ?? {}).length > 0;
1039
- }
1040
- merge(data) {
1041
- this.page = { ...this.page, ...data };
1042
- }
1043
- setFlash(flash) {
1044
- this.page = { ...this.page, flash };
1045
- this.onFlashCallback?.(flash);
1046
- }
1047
- setUrlHash(hash) {
1048
- if (!this.page.url.includes(hash)) {
1049
- this.page.url += hash;
1050
- }
1051
- }
1052
- remember(data) {
1053
- this.page.rememberedState = data;
1054
- }
1055
- swap({
1056
- component,
1057
- page: page2,
1058
- preserveState,
1059
- viewTransition
1060
- }) {
1061
- const doSwap = () => this.swapComponent({ component, page: page2, preserveState });
1062
- if (!viewTransition || !document?.startViewTransition) {
1063
- return doSwap();
1064
- }
1065
- const viewTransitionCallback = typeof viewTransition === "boolean" ? () => null : viewTransition;
1066
- return new Promise((resolve) => {
1067
- const transitionResult = document.startViewTransition(() => doSwap().then(resolve));
1068
- viewTransitionCallback(transitionResult);
1069
- });
1070
- }
1071
- resolve(component) {
1072
- return Promise.resolve(this.resolveComponent(component));
1073
- }
1074
- isTheSame(page2) {
1075
- return this.page.component === page2.component;
1076
- }
1077
- on(event, callback) {
1078
- this.listeners.push({ event, callback });
1079
- return () => {
1080
- this.listeners = this.listeners.filter((listener) => listener.event !== event && listener.callback !== callback);
1081
- };
1082
- }
1083
- fireEventsFor(event) {
1084
- this.listeners.filter((listener) => listener.event === event).forEach((listener) => listener.callback());
1085
- }
1086
- mergeOncePropsIntoResponse(response, { force = false } = {}) {
1087
- Object.entries(response.onceProps ?? {}).forEach(([key, onceProp]) => {
1088
- const existingOnceProp = this.page.onceProps?.[key];
1089
- if (existingOnceProp === void 0) {
1090
- return;
1091
- }
1092
- if (force || response.props[onceProp.prop] === void 0) {
1093
- response.props[onceProp.prop] = this.page.props[existingOnceProp.prop];
1094
- response.onceProps[key].expiresAt = existingOnceProp.expiresAt;
1095
- }
1096
- });
1097
- }
1098
- };
1099
- var page = new CurrentPage();
1100
-
1101
- // src/queue.ts
1102
- var Queue = class {
1103
- constructor() {
1104
- this.items = [];
1105
- this.processingPromise = null;
1106
- }
1107
- add(item) {
1108
- this.items.push(item);
1109
- return this.process();
1110
- }
1111
- process() {
1112
- this.processingPromise ?? (this.processingPromise = this.processNext().finally(() => {
1113
- this.processingPromise = null;
1114
- }));
1115
- return this.processingPromise;
1116
- }
1117
- processNext() {
1118
- const next = this.items.shift();
1119
- if (next) {
1120
- return Promise.resolve(next()).then(() => this.processNext());
1121
- }
1122
- return Promise.resolve();
1123
- }
1124
- };
1125
-
1126
- // src/history.ts
1127
- var isServer2 = typeof window === "undefined";
1128
- var queue = new Queue();
1129
- var isChromeIOS = !isServer2 && /CriOS/.test(window.navigator.userAgent);
1130
- var History = class {
1131
- constructor() {
1132
- this.rememberedState = "rememberedState";
1133
- this.scrollRegions = "scrollRegions";
1134
- this.preserveUrl = false;
1135
- this.current = {};
1136
- // We need initialState for `restore`
1137
- this.initialState = null;
1138
- }
1139
- remember(data, key) {
1140
- this.replaceState({
1141
- ...page.getWithoutFlashData(),
1142
- rememberedState: {
1143
- ...page.get()?.rememberedState ?? {},
1144
- [key]: data
1145
- }
1146
- });
1147
- }
1148
- restore(key) {
1149
- if (!isServer2) {
1150
- return this.current[this.rememberedState]?.[key] !== void 0 ? this.current[this.rememberedState]?.[key] : this.initialState?.[this.rememberedState]?.[key];
1151
- }
1152
- }
1153
- pushState(page2, cb = null) {
1154
- if (isServer2) {
1155
- return;
1156
- }
1157
- if (this.preserveUrl) {
1158
- cb && cb();
1159
- return;
1160
- }
1161
- this.current = page2;
1162
- queue.add(() => {
1163
- return this.getPageData(page2).then((data) => {
1164
- const doPush = () => this.doPushState({ page: data }, page2.url).then(() => cb?.());
1165
- if (isChromeIOS) {
1166
- return new Promise((resolve) => {
1167
- setTimeout(() => doPush().then(resolve));
1168
- });
1169
- }
1170
- return doPush();
1171
- });
1172
- });
1173
- }
1174
- clonePageProps(page2) {
1175
- try {
1176
- structuredClone(page2.props);
1177
- return page2;
1178
- } catch {
1179
- return {
1180
- ...page2,
1181
- props: cloneDeep2(page2.props)
1182
- };
1183
- }
1184
- }
1185
- getPageData(page2) {
1186
- const pageWithClonedProps = this.clonePageProps(page2);
1187
- return new Promise((resolve) => {
1188
- return page2.encryptHistory ? encryptHistory(pageWithClonedProps).then(resolve) : resolve(pageWithClonedProps);
1189
- });
1190
- }
1191
- processQueue() {
1192
- return queue.process();
1193
- }
1194
- decrypt(page2 = null) {
1195
- if (isServer2) {
1196
- return Promise.resolve(page2 ?? page.get());
1197
- }
1198
- const pageData = page2 ?? window.history.state?.page;
1199
- return this.decryptPageData(pageData).then((data) => {
1200
- if (!data) {
1201
- throw new Error("Unable to decrypt history");
1202
- }
1203
- if (this.initialState === null) {
1204
- this.initialState = data ?? void 0;
1205
- } else {
1206
- this.current = data ?? {};
1207
- }
1208
- return data;
1209
- });
1210
- }
1211
- decryptPageData(pageData) {
1212
- return pageData instanceof ArrayBuffer ? decryptHistory(pageData) : Promise.resolve(pageData);
1213
- }
1214
- saveScrollPositions(scrollRegions) {
1215
- queue.add(() => {
1216
- return Promise.resolve().then(() => {
1217
- if (!window.history.state?.page) {
1218
- return;
1219
- }
1220
- if (isEqual(this.getScrollRegions(), scrollRegions)) {
1221
- return;
1222
- }
1223
- return this.doReplaceState({
1224
- page: window.history.state.page,
1225
- scrollRegions
1226
- });
1227
- });
1228
- });
1229
- }
1230
- saveDocumentScrollPosition(scrollRegion) {
1231
- queue.add(() => {
1232
- return Promise.resolve().then(() => {
1233
- if (!window.history.state?.page) {
1234
- return;
1235
- }
1236
- if (isEqual(this.getDocumentScrollPosition(), scrollRegion)) {
1237
- return;
1238
- }
1239
- return this.doReplaceState({
1240
- page: window.history.state.page,
1241
- documentScrollPosition: scrollRegion
1242
- });
1243
- });
1244
- });
1245
- }
1246
- getScrollRegions() {
1247
- return window.history.state?.scrollRegions || [];
1248
- }
1249
- getDocumentScrollPosition() {
1250
- return window.history.state?.documentScrollPosition || { top: 0, left: 0 };
1251
- }
1252
- replaceState(page2, cb = null) {
1253
- if (isEqual(this.current, page2)) {
1254
- cb && cb();
1255
- return;
1256
- }
1257
- const { flash, ...pageWithoutFlash } = page2;
1258
- page.merge(pageWithoutFlash);
1259
- if (isServer2) {
1260
- return;
1261
- }
1262
- if (this.preserveUrl) {
1263
- cb && cb();
1264
- return;
1265
- }
1266
- this.current = page2;
1267
- queue.add(() => {
1268
- return this.getPageData(page2).then((data) => {
1269
- const doReplace = () => this.doReplaceState({ page: data }, page2.url).then(() => cb?.());
1270
- if (isChromeIOS) {
1271
- return new Promise((resolve) => {
1272
- setTimeout(() => doReplace().then(resolve));
1273
- });
1274
- }
1275
- return doReplace();
1276
- });
1277
- });
1278
- }
1279
- isHistoryThrottleError(error) {
1280
- return error instanceof Error && error.name === "SecurityError" && (error.message.includes("history.pushState") || error.message.includes("history.replaceState"));
1281
- }
1282
- isQuotaExceededError(error) {
1283
- return error instanceof Error && error.name === "QuotaExceededError";
1284
- }
1285
- withThrottleProtection(cb) {
1286
- return Promise.resolve().then(() => {
1287
- try {
1288
- return cb();
1289
- } catch (error) {
1290
- if (!this.isHistoryThrottleError(error)) {
1291
- throw error;
1292
- }
1293
- console.error(error.message);
1294
- }
1295
- });
1296
- }
1297
- doReplaceState(data, url) {
1298
- return this.withThrottleProtection(() => {
1299
- window.history.replaceState(
1300
- {
1301
- ...data,
1302
- scrollRegions: data.scrollRegions ?? window.history.state?.scrollRegions,
1303
- documentScrollPosition: data.documentScrollPosition ?? window.history.state?.documentScrollPosition
1304
- },
1305
- "",
1306
- url
1307
- );
1308
- });
1309
- }
1310
- doPushState(data, url) {
1311
- return this.withThrottleProtection(() => {
1312
- try {
1313
- window.history.pushState(data, "", url);
1314
- } catch (error) {
1315
- if (!this.isQuotaExceededError(error)) {
1316
- throw error;
1317
- }
1318
- eventHandler.fireInternalEvent("historyQuotaExceeded", url);
1319
- }
1320
- });
1321
- }
1322
- getState(key, defaultValue) {
1323
- return this.current?.[key] ?? defaultValue;
1324
- }
1325
- deleteState(key) {
1326
- if (this.current[key] !== void 0) {
1327
- delete this.current[key];
1328
- this.replaceState(this.current);
1329
- }
1330
- }
1331
- clearInitialState(key) {
1332
- if (this.initialState && this.initialState[key] !== void 0) {
1333
- delete this.initialState[key];
1334
- }
1335
- }
1336
- browserHasHistoryEntry() {
1337
- return !isServer2 && !!window.history.state?.page;
1338
- }
1339
- clear() {
1340
- SessionStorage.remove(historySessionStorageKeys.key);
1341
- SessionStorage.remove(historySessionStorageKeys.iv);
1342
- }
1343
- setCurrent(page2) {
1344
- this.current = page2;
1345
- }
1346
- isValidState(state) {
1347
- return !!state.page;
1348
- }
1349
- getAllState() {
1350
- return this.current;
1351
- }
1352
- };
1353
- if (typeof window !== "undefined" && window.history.scrollRestoration) {
1354
- window.history.scrollRestoration = "manual";
1355
- }
1356
- var history = new History();
1357
-
1358
- // src/eventHandler.ts
1359
- var EventHandler = class {
1360
- constructor() {
1361
- this.internalListeners = [];
1362
- }
1363
- init() {
1364
- if (typeof window !== "undefined") {
1365
- window.addEventListener("popstate", this.handlePopstateEvent.bind(this));
1366
- window.addEventListener("pageshow", this.handlePageshowEvent.bind(this));
1367
- window.addEventListener("scroll", debounce(Scroll.onWindowScroll.bind(Scroll), 100), true);
1368
- }
1369
- if (typeof document !== "undefined") {
1370
- document.addEventListener("scroll", debounce(Scroll.onScroll.bind(Scroll), 100), true);
1371
- }
1372
- }
1373
- onGlobalEvent(type, callback) {
1374
- const listener = ((event) => {
1375
- const response = callback(event);
1376
- if (event.cancelable && !event.defaultPrevented && response === false) {
1377
- event.preventDefault();
1378
- }
1379
- });
1380
- return this.registerListener(`inertia:${type}`, listener);
1381
- }
1382
- on(event, callback) {
1383
- this.internalListeners.push({ event, listener: callback });
1384
- return () => {
1385
- this.internalListeners = this.internalListeners.filter((listener) => listener.listener !== callback);
1386
- };
1387
- }
1388
- onMissingHistoryItem() {
1389
- page.clear();
1390
- this.fireInternalEvent("missingHistoryItem");
1391
- }
1392
- fireInternalEvent(event, ...args) {
1393
- this.internalListeners.filter((listener) => listener.event === event).forEach((listener) => listener.listener(...args));
1394
- }
1395
- registerListener(type, listener) {
1396
- document.addEventListener(type, listener);
1397
- return () => document.removeEventListener(type, listener);
1398
- }
1399
- // bfcache restores pages without firing `popstate`, so we use `pageshow` to
1400
- // re-validate encrypted history entries after `clearHistory` removed the keys.
1401
- // https://web.dev/articles/bfcache
1402
- handlePageshowEvent(event) {
1403
- if (event.persisted) {
1404
- history.decrypt().catch(() => this.onMissingHistoryItem());
1405
- }
1406
- }
1407
- handlePopstateEvent(event) {
1408
- const state = event.state || null;
1409
- if (state === null) {
1410
- const url = hrefToUrl(page.get().url);
1411
- url.hash = window.location.hash;
1412
- history.replaceState({ ...page.getWithoutFlashData(), url: url.href });
1413
- Scroll.reset();
1414
- return;
1415
- }
1416
- if (!history.isValidState(state)) {
1417
- return this.onMissingHistoryItem();
1418
- }
1419
- history.decrypt(state.page).then((data) => {
1420
- if (page.get().version !== data.version) {
1421
- this.onMissingHistoryItem();
1422
- return;
1423
- }
1424
- router.cancelAll({ prefetch: false });
1425
- page.setQuietly(data, { preserveState: false }).then(() => {
1426
- Scroll.restore(history.getScrollRegions());
1427
- fireNavigateEvent(page.get());
1428
- const pendingDeferred = {};
1429
- const pageProps = page.get().props;
1430
- for (const [group, props] of Object.entries(data.initialDeferredProps ?? data.deferredProps ?? {})) {
1431
- const missing = props.filter((prop) => pageProps[prop] === void 0);
1432
- if (missing.length > 0) {
1433
- pendingDeferred[group] = missing;
1434
- }
1435
- }
1436
- if (Object.keys(pendingDeferred).length > 0) {
1437
- this.fireInternalEvent("loadDeferredProps", pendingDeferred);
1438
- }
1439
- });
1440
- }).catch(() => {
1441
- this.onMissingHistoryItem();
1442
- });
1443
- }
1444
- };
1445
- var eventHandler = new EventHandler();
1446
-
1447
- // src/navigationType.ts
1448
- var NavigationType = class {
1449
- constructor() {
1450
- this.type = this.resolveType();
1451
- }
1452
- resolveType() {
1453
- if (typeof window === "undefined") {
1454
- return "navigate";
1455
- }
1456
- if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) {
1457
- return window.performance.getEntriesByType("navigation")[0].type;
1458
- }
1459
- return "navigate";
1460
- }
1461
- get() {
1462
- return this.type;
1463
- }
1464
- isBackForward() {
1465
- return this.type === "back_forward";
1466
- }
1467
- isReload() {
1468
- return this.type === "reload";
1469
- }
1470
- };
1471
- var navigationType = new NavigationType();
1472
-
1473
- // src/initialVisit.ts
1474
- var InitialVisit = class {
1475
- static handle() {
1476
- this.clearRememberedStateOnReload();
1477
- const scenarios = [this.handleBackForward, this.handleLocation, this.handleDefault];
1478
- scenarios.find((handler) => handler.bind(this)());
1479
- }
1480
- static clearRememberedStateOnReload() {
1481
- if (navigationType.isReload()) {
1482
- history.deleteState(history.rememberedState);
1483
- history.clearInitialState(history.rememberedState);
1484
- }
1485
- }
1486
- static handleBackForward() {
1487
- if (!navigationType.isBackForward() || !history.browserHasHistoryEntry()) {
1488
- return false;
1489
- }
1490
- const scrollRegions = history.getScrollRegions();
1491
- history.decrypt().then((data) => {
1492
- page.set(data, { preserveScroll: true, preserveState: true }).then(() => {
1493
- Scroll.restore(scrollRegions);
1494
- fireNavigateEvent(page.get());
1495
- });
1496
- }).catch(() => {
1497
- eventHandler.onMissingHistoryItem();
1498
- });
1499
- return true;
1500
- }
1501
- /**
1502
- * @link https://inertiajs.com/redirects#external-redirects
1503
- */
1504
- static handleLocation() {
1505
- if (!SessionStorage.exists(SessionStorage.locationVisitKey)) {
1506
- return false;
1507
- }
1508
- const locationVisit = SessionStorage.get(SessionStorage.locationVisitKey) || {};
1509
- SessionStorage.remove(SessionStorage.locationVisitKey);
1510
- if (typeof window !== "undefined") {
1511
- page.setUrlHash(window.location.hash);
1512
- }
1513
- history.decrypt(page.get()).then(() => {
1514
- const rememberedState = history.getState(history.rememberedState, {});
1515
- const scrollRegions = history.getScrollRegions();
1516
- page.remember(rememberedState);
1517
- page.set(page.get(), {
1518
- preserveScroll: locationVisit.preserveScroll,
1519
- preserveState: true
1520
- }).then(() => {
1521
- if (locationVisit.preserveScroll) {
1522
- Scroll.restore(scrollRegions);
1523
- }
1524
- fireNavigateEvent(page.get());
1525
- });
1526
- }).catch(() => {
1527
- eventHandler.onMissingHistoryItem();
1528
- });
1529
- return true;
1530
- }
1531
- static handleDefault() {
1532
- if (typeof window !== "undefined") {
1533
- page.setUrlHash(window.location.hash);
1534
- }
1535
- page.set(page.get(), { preserveScroll: true, preserveState: true }).then(() => {
1536
- if (navigationType.isReload()) {
1537
- Scroll.restore(history.getScrollRegions());
1538
- } else {
1539
- Scroll.scrollToAnchor();
1540
- }
1541
- const page2 = page.get();
1542
- fireNavigateEvent(page2);
1543
- const flash = page2.flash;
1544
- if (Object.keys(flash).length > 0) {
1545
- queueMicrotask(() => fireFlashEvent(flash));
1546
- }
1547
- });
1548
- }
1549
- };
1550
-
1551
- // src/poll.ts
1552
- var Poll = class {
1553
- constructor(interval, cb, options) {
1554
- this.id = null;
1555
- this.throttle = false;
1556
- this.keepAlive = false;
1557
- this.cbCount = 0;
1558
- this.keepAlive = options.keepAlive ?? false;
1559
- this.cb = cb;
1560
- this.interval = interval;
1561
- if (options.autoStart ?? true) {
1562
- this.start();
1563
- }
1564
- }
1565
- stop() {
1566
- if (this.id) {
1567
- clearInterval(this.id);
1568
- }
1569
- }
1570
- start() {
1571
- if (typeof window === "undefined") {
1572
- return;
1573
- }
1574
- this.stop();
1575
- this.id = window.setInterval(() => {
1576
- if (!this.throttle || this.cbCount % 10 === 0) {
1577
- this.cb();
1578
- }
1579
- if (this.throttle) {
1580
- this.cbCount++;
1581
- }
1582
- }, this.interval);
1583
- }
1584
- isInBackground(hidden) {
1585
- this.throttle = this.keepAlive ? false : hidden;
1586
- if (this.throttle) {
1587
- this.cbCount = 0;
1588
- }
1589
- }
1590
- };
1591
-
1592
- // src/polls.ts
1593
- var Polls = class {
1594
- constructor() {
1595
- this.polls = [];
1596
- this.setupVisibilityListener();
1597
- }
1598
- add(interval, cb, options) {
1599
- const poll = new Poll(interval, cb, options);
1600
- this.polls.push(poll);
1601
- return {
1602
- stop: () => poll.stop(),
1603
- start: () => poll.start()
1604
- };
1605
- }
1606
- clear() {
1607
- this.polls.forEach((poll) => poll.stop());
1608
- this.polls = [];
1609
- }
1610
- setupVisibilityListener() {
1611
- if (typeof document === "undefined") {
1612
- return;
1613
- }
1614
- document.addEventListener(
1615
- "visibilitychange",
1616
- () => {
1617
- this.polls.forEach((poll) => poll.isInBackground(document.hidden));
1618
- },
1619
- false
1620
- );
1621
- }
1622
- };
1623
- var polls = new Polls();
1624
-
1625
- // src/request.ts
1626
- import { default as axios } from "axios";
1627
-
1628
- // src/requestParams.ts
1629
- var RequestParams = class _RequestParams {
1630
- constructor(params) {
1631
- this.callbacks = [];
1632
- if (!params.prefetch) {
1633
- this.params = params;
1634
- } else {
1635
- const wrappedCallbacks = {
1636
- onBefore: this.wrapCallback(params, "onBefore"),
1637
- onBeforeUpdate: this.wrapCallback(params, "onBeforeUpdate"),
1638
- onStart: this.wrapCallback(params, "onStart"),
1639
- onProgress: this.wrapCallback(params, "onProgress"),
1640
- onFinish: this.wrapCallback(params, "onFinish"),
1641
- onCancel: this.wrapCallback(params, "onCancel"),
1642
- onSuccess: this.wrapCallback(params, "onSuccess"),
1643
- onError: this.wrapCallback(params, "onError"),
1644
- onFlash: this.wrapCallback(params, "onFlash"),
1645
- onCancelToken: this.wrapCallback(params, "onCancelToken"),
1646
- onPrefetched: this.wrapCallback(params, "onPrefetched"),
1647
- onPrefetching: this.wrapCallback(params, "onPrefetching")
1648
- };
1649
- this.params = {
1650
- ...params,
1651
- ...wrappedCallbacks,
1652
- onPrefetchResponse: params.onPrefetchResponse || (() => {
1653
- }),
1654
- onPrefetchError: params.onPrefetchError || (() => {
1655
- })
1656
- };
1657
- }
1658
- }
1659
- static create(params) {
1660
- return new _RequestParams(params);
1661
- }
1662
- data() {
1663
- return this.params.method === "get" ? null : this.params.data;
1664
- }
1665
- queryParams() {
1666
- return this.params.method === "get" ? this.params.data : {};
1667
- }
1668
- isPartial() {
1669
- return this.params.only.length > 0 || this.params.except.length > 0 || this.params.reset.length > 0;
1670
- }
1671
- isPrefetch() {
1672
- return this.params.prefetch === true;
1673
- }
1674
- isDeferredPropsRequest() {
1675
- return this.params.deferredProps === true;
1676
- }
1677
- onCancelToken(cb) {
1678
- this.params.onCancelToken({
1679
- cancel: cb
1680
- });
1681
- }
1682
- markAsFinished() {
1683
- this.params.completed = true;
1684
- this.params.cancelled = false;
1685
- this.params.interrupted = false;
1686
- }
1687
- markAsCancelled({ cancelled = true, interrupted = false }) {
1688
- this.params.onCancel();
1689
- this.params.completed = false;
1690
- this.params.cancelled = cancelled;
1691
- this.params.interrupted = interrupted;
1692
- }
1693
- wasCancelledAtAll() {
1694
- return this.params.cancelled || this.params.interrupted;
1695
- }
1696
- onFinish() {
1697
- this.params.onFinish(this.params);
1698
- }
1699
- onStart() {
1700
- this.params.onStart(this.params);
1701
- }
1702
- onPrefetching() {
1703
- this.params.onPrefetching(this.params);
1704
- }
1705
- onPrefetchResponse(response) {
1706
- if (this.params.onPrefetchResponse) {
1707
- this.params.onPrefetchResponse(response);
1708
- }
1709
- }
1710
- onPrefetchError(error) {
1711
- if (this.params.onPrefetchError) {
1712
- this.params.onPrefetchError(error);
1713
- }
1714
- }
1715
- all() {
1716
- return this.params;
1717
- }
1718
- headers() {
1719
- const headers = {
1720
- ...this.params.headers
1721
- };
1722
- if (this.isPartial()) {
1723
- headers["X-Inertia-Partial-Component"] = page.get().component;
1724
- }
1725
- const only = this.params.only.concat(this.params.reset);
1726
- if (only.length > 0) {
1727
- headers["X-Inertia-Partial-Data"] = only.join(",");
1728
- }
1729
- if (this.params.except.length > 0) {
1730
- headers["X-Inertia-Partial-Except"] = this.params.except.join(",");
1731
- }
1732
- if (this.params.reset.length > 0) {
1733
- headers["X-Inertia-Reset"] = this.params.reset.join(",");
1734
- }
1735
- if (this.params.errorBag && this.params.errorBag.length > 0) {
1736
- headers["X-Inertia-Error-Bag"] = this.params.errorBag;
1737
- }
1738
- return headers;
1739
- }
1740
- setPreserveOptions(page2) {
1741
- this.params.preserveScroll = _RequestParams.resolvePreserveOption(this.params.preserveScroll, page2);
1742
- this.params.preserveState = _RequestParams.resolvePreserveOption(this.params.preserveState, page2);
1743
- }
1744
- runCallbacks() {
1745
- this.callbacks.forEach(({ name, args }) => {
1746
- this.params[name](...args);
1747
- });
1748
- }
1749
- merge(toMerge) {
1750
- this.params = {
1751
- ...this.params,
1752
- ...toMerge
1753
- };
1754
- }
1755
- wrapCallback(params, name) {
1756
- return (...args) => {
1757
- this.recordCallback(name, args);
1758
- params[name](...args);
1759
- };
1760
- }
1761
- recordCallback(name, args) {
1762
- this.callbacks.push({ name, args });
1763
- }
1764
- static resolvePreserveOption(value, page2) {
1765
- if (typeof value === "function") {
1766
- return value(page2);
1767
- }
1768
- if (value === "errors") {
1769
- return Object.keys(page2.props.errors || {}).length > 0;
1770
- }
1771
- return value;
1772
- }
1773
- };
1774
-
1775
- // src/response.ts
1776
- import { get as get2, isEqual as isEqual2, set as set2 } from "lodash-es";
1777
-
1778
- // src/modal.ts
1779
- var modal_default = {
1780
- modal: null,
1781
- listener: null,
1782
- createIframeAndPage(html) {
1783
- if (typeof html === "object") {
1784
- html = `All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.<hr>${JSON.stringify(
1785
- html
1786
- )}`;
1787
- }
1788
- const page2 = document.createElement("html");
1789
- page2.innerHTML = html;
1790
- page2.querySelectorAll("a").forEach((a) => a.setAttribute("target", "_top"));
1791
- const iframe = document.createElement("iframe");
1792
- iframe.style.backgroundColor = "white";
1793
- iframe.style.borderRadius = "5px";
1794
- iframe.style.width = "100%";
1795
- iframe.style.height = "100%";
1796
- return { iframe, page: page2 };
1797
- },
1798
- show(html) {
1799
- const { iframe, page: page2 } = this.createIframeAndPage(html);
1800
- this.modal = document.createElement("div");
1801
- this.modal.style.position = "fixed";
1802
- this.modal.style.width = "100vw";
1803
- this.modal.style.height = "100vh";
1804
- this.modal.style.padding = "50px";
1805
- this.modal.style.boxSizing = "border-box";
1806
- this.modal.style.backgroundColor = "rgba(0, 0, 0, .6)";
1807
- this.modal.style.zIndex = 2e5;
1808
- this.modal.addEventListener("click", () => this.hide());
1809
- this.modal.appendChild(iframe);
1810
- document.body.prepend(this.modal);
1811
- document.body.style.overflow = "hidden";
1812
- if (!iframe.contentWindow) {
1813
- throw new Error("iframe not yet ready.");
1814
- }
1815
- iframe.contentWindow.document.open();
1816
- iframe.contentWindow.document.write(page2.outerHTML);
1817
- iframe.contentWindow.document.close();
1818
- this.listener = this.hideOnEscape.bind(this);
1819
- document.addEventListener("keydown", this.listener);
1820
- },
1821
- hide() {
1822
- this.modal.outerHTML = "";
1823
- this.modal = null;
1824
- document.body.style.overflow = "visible";
1825
- document.removeEventListener("keydown", this.listener);
1826
- },
1827
- hideOnEscape(event) {
1828
- if (event.keyCode === 27) {
1829
- this.hide();
1830
- }
1831
- }
1832
- };
1833
-
1834
- // src/dialog.ts
1835
- var dialog_default = {
1836
- show(html) {
1837
- const { iframe, page: page2 } = modal_default.createIframeAndPage(html);
1838
- iframe.style.boxSizing = "border-box";
1839
- iframe.style.display = "block";
1840
- const dialog = document.createElement("dialog");
1841
- dialog.id = "inertia-error-dialog";
1842
- Object.assign(dialog.style, {
1843
- width: "calc(100vw - 100px)",
1844
- height: "calc(100vh - 100px)",
1845
- padding: "0",
1846
- margin: "auto",
1847
- border: "none",
1848
- backgroundColor: "transparent"
1849
- });
1850
- const dialogStyleElement = document.createElement("style");
1851
- dialogStyleElement.textContent = `
1852
- dialog#inertia-error-dialog::backdrop {
1853
- background-color: rgba(0, 0, 0, 0.6);
1854
- }
1855
-
1856
- dialog#inertia-error-dialog:focus {
1857
- outline: none;
1858
- }
1859
- `;
1860
- document.head.appendChild(dialogStyleElement);
1861
- dialog.addEventListener("click", (event) => {
1862
- if (event.target === dialog) {
1863
- dialog.close();
1864
- }
1865
- });
1866
- dialog.addEventListener("close", () => {
1867
- dialogStyleElement.remove();
1868
- dialog.remove();
1869
- });
1870
- dialog.appendChild(iframe);
1871
- document.body.prepend(dialog);
1872
- dialog.showModal();
1873
- dialog.focus();
1874
- if (!iframe.contentWindow) {
1875
- throw new Error("iframe not yet ready.");
1876
- }
1877
- iframe.contentWindow.document.open();
1878
- iframe.contentWindow.document.write(page2.outerHTML);
1879
- iframe.contentWindow.document.close();
1880
- }
1881
- };
1882
-
1883
- // src/response.ts
1884
- var queue2 = new Queue();
1885
- var Response = class _Response {
1886
- constructor(requestParams, response, originatingPage) {
1887
- this.requestParams = requestParams;
1888
- this.response = response;
1889
- this.originatingPage = originatingPage;
1890
- this.wasPrefetched = false;
1891
- }
1892
- static create(params, response, originatingPage) {
1893
- return new _Response(params, response, originatingPage);
1894
- }
1895
- async handlePrefetch() {
1896
- if (isSameUrlWithoutHash(this.requestParams.all().url, window.location)) {
1897
- this.handle();
1898
- }
1899
- }
1900
- async handle() {
1901
- return queue2.add(() => this.process());
1902
- }
1903
- async process() {
1904
- if (this.requestParams.all().prefetch) {
1905
- this.wasPrefetched = true;
1906
- this.requestParams.all().prefetch = false;
1907
- this.requestParams.all().onPrefetched(this.response, this.requestParams.all());
1908
- firePrefetchedEvent(this.response, this.requestParams.all());
1909
- return Promise.resolve();
1910
- }
1911
- this.requestParams.runCallbacks();
1912
- if (!this.isInertiaResponse()) {
1913
- return this.handleNonInertiaResponse();
1914
- }
1915
- await history.processQueue();
1916
- history.preserveUrl = this.requestParams.all().preserveUrl;
1917
- const previousFlash = page.get().flash;
1918
- await this.setPage();
1919
- const errors = page.get().props.errors || {};
1920
- if (Object.keys(errors).length > 0) {
1921
- const scopedErrors = this.getScopedErrors(errors);
1922
- fireErrorEvent(scopedErrors);
1923
- return this.requestParams.all().onError(scopedErrors);
1924
- }
1925
- router.flushByCacheTags(this.requestParams.all().invalidateCacheTags || []);
1926
- if (!this.wasPrefetched) {
1927
- router.flush(page.get().url);
1928
- }
1929
- const { flash } = page.get();
1930
- if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual2(flash, previousFlash))) {
1931
- fireFlashEvent(flash);
1932
- this.requestParams.all().onFlash(flash);
1933
- }
1934
- fireSuccessEvent(page.get());
1935
- await this.requestParams.all().onSuccess(page.get());
1936
- history.preserveUrl = false;
1937
- }
1938
- mergeParams(params) {
1939
- this.requestParams.merge(params);
1940
- }
1941
- getPageResponse() {
1942
- const data = this.getDataFromResponse(this.response.data);
1943
- if (typeof data === "object") {
1944
- return this.response.data = { ...data, flash: data.flash ?? {} };
1945
- }
1946
- return this.response.data = data;
1947
- }
1948
- async handleNonInertiaResponse() {
1949
- if (this.isLocationVisit()) {
1950
- const locationUrl = hrefToUrl(this.getHeader("x-inertia-location"));
1951
- setHashIfSameUrl(this.requestParams.all().url, locationUrl);
1952
- return this.locationVisit(locationUrl);
1953
- }
1954
- const response = {
1955
- ...this.response,
1956
- data: this.getDataFromResponse(this.response.data)
1957
- };
1958
- if (fireInvalidEvent(response)) {
1959
- return config.get("future.useDialogForErrorModal") ? dialog_default.show(response.data) : modal_default.show(response.data);
1960
- }
1961
- }
1962
- isInertiaResponse() {
1963
- return this.hasHeader("x-inertia");
1964
- }
1965
- hasStatus(status2) {
1966
- return this.response.status === status2;
1967
- }
1968
- getHeader(header) {
1969
- return this.response.headers[header];
1970
- }
1971
- hasHeader(header) {
1972
- return this.getHeader(header) !== void 0;
1973
- }
1974
- isLocationVisit() {
1975
- return this.hasStatus(409) && this.hasHeader("x-inertia-location");
1976
- }
1977
- /**
1978
- * @link https://inertiajs.com/redirects#external-redirects
1979
- */
1980
- locationVisit(url) {
1981
- try {
1982
- SessionStorage.set(SessionStorage.locationVisitKey, {
1983
- preserveScroll: this.requestParams.all().preserveScroll === true
1984
- });
1985
- if (typeof window === "undefined") {
1986
- return;
1987
- }
1988
- if (isSameUrlWithoutHash(window.location, url)) {
1989
- window.location.reload();
1990
- } else {
1991
- window.location.href = url.href;
1992
- }
1993
- } catch (error) {
1994
- return false;
1995
- }
1996
- }
1997
- async setPage() {
1998
- const pageResponse = this.getPageResponse();
1999
- if (!this.shouldSetPage(pageResponse)) {
2000
- return Promise.resolve();
2001
- }
2002
- this.mergeProps(pageResponse);
2003
- page.mergeOncePropsIntoResponse(pageResponse);
2004
- this.preserveEqualProps(pageResponse);
2005
- await this.setRememberedState(pageResponse);
2006
- this.requestParams.setPreserveOptions(pageResponse);
2007
- pageResponse.url = history.preserveUrl ? page.get().url : this.pageUrl(pageResponse);
2008
- this.requestParams.all().onBeforeUpdate(pageResponse);
2009
- fireBeforeUpdateEvent(pageResponse);
2010
- return page.set(pageResponse, {
2011
- replace: this.requestParams.all().replace,
2012
- preserveScroll: this.requestParams.all().preserveScroll,
2013
- preserveState: this.requestParams.all().preserveState,
2014
- viewTransition: this.requestParams.all().viewTransition
2015
- });
2016
- }
2017
- getDataFromResponse(response) {
2018
- if (typeof response !== "string") {
2019
- return response;
2020
- }
2021
- try {
2022
- return JSON.parse(response);
2023
- } catch (error) {
2024
- return response;
2025
- }
2026
- }
2027
- shouldSetPage(pageResponse) {
2028
- if (!this.requestParams.all().async) {
2029
- return true;
2030
- }
2031
- if (this.originatingPage.component !== pageResponse.component) {
2032
- return true;
2033
- }
2034
- if (this.originatingPage.component !== page.get().component) {
2035
- return false;
2036
- }
2037
- const originatingUrl = hrefToUrl(this.originatingPage.url);
2038
- const currentPageUrl = hrefToUrl(page.get().url);
2039
- return originatingUrl.origin === currentPageUrl.origin && originatingUrl.pathname === currentPageUrl.pathname;
2040
- }
2041
- pageUrl(pageResponse) {
2042
- const responseUrl = hrefToUrl(pageResponse.url);
2043
- setHashIfSameUrl(this.requestParams.all().url, responseUrl);
2044
- return responseUrl.pathname + responseUrl.search + responseUrl.hash;
2045
- }
2046
- preserveEqualProps(pageResponse) {
2047
- if (pageResponse.component !== page.get().component || config.get("future.preserveEqualProps") !== true) {
2048
- return;
2049
- }
2050
- const currentPageProps = page.get().props;
2051
- Object.entries(pageResponse.props).forEach(([key, value]) => {
2052
- if (isEqual2(value, currentPageProps[key])) {
2053
- pageResponse.props[key] = currentPageProps[key];
2054
- }
2055
- });
2056
- }
2057
- mergeProps(pageResponse) {
2058
- if (!this.requestParams.isPartial() || pageResponse.component !== page.get().component) {
2059
- return;
2060
- }
2061
- const propsToAppend = pageResponse.mergeProps || [];
2062
- const propsToPrepend = pageResponse.prependProps || [];
2063
- const propsToDeepMerge = pageResponse.deepMergeProps || [];
2064
- const matchPropsOn = pageResponse.matchPropsOn || [];
2065
- const mergeProp = (prop, shouldAppend) => {
2066
- const currentProp = get2(page.get().props, prop);
2067
- const incomingProp = get2(pageResponse.props, prop);
2068
- if (Array.isArray(incomingProp)) {
2069
- const newArray = this.mergeOrMatchItems(
2070
- currentProp || [],
2071
- incomingProp,
2072
- prop,
2073
- matchPropsOn,
2074
- shouldAppend
2075
- );
2076
- set2(pageResponse.props, prop, newArray);
2077
- } else if (typeof incomingProp === "object" && incomingProp !== null) {
2078
- const newObject = {
2079
- ...currentProp || {},
2080
- ...incomingProp
2081
- };
2082
- set2(pageResponse.props, prop, newObject);
2083
- }
2084
- };
2085
- propsToAppend.forEach((prop) => mergeProp(prop, true));
2086
- propsToPrepend.forEach((prop) => mergeProp(prop, false));
2087
- propsToDeepMerge.forEach((prop) => {
2088
- const currentProp = page.get().props[prop];
2089
- const incomingProp = pageResponse.props[prop];
2090
- const deepMerge = (target, source, matchProp) => {
2091
- if (Array.isArray(source)) {
2092
- return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn);
2093
- }
2094
- if (typeof source === "object" && source !== null) {
2095
- return Object.keys(source).reduce(
2096
- (acc, key) => {
2097
- acc[key] = deepMerge(target ? target[key] : void 0, source[key], `${matchProp}.${key}`);
2098
- return acc;
2099
- },
2100
- { ...target }
2101
- );
2102
- }
2103
- return source;
2104
- };
2105
- pageResponse.props[prop] = deepMerge(currentProp, incomingProp, prop);
2106
- });
2107
- pageResponse.props = { ...page.get().props, ...pageResponse.props };
2108
- if (this.requestParams.isDeferredPropsRequest()) {
2109
- const currentErrors = page.get().props.errors;
2110
- if (currentErrors && Object.keys(currentErrors).length > 0) {
2111
- pageResponse.props.errors = currentErrors;
2112
- }
2113
- }
2114
- if (page.get().scrollProps) {
2115
- pageResponse.scrollProps = {
2116
- ...page.get().scrollProps || {},
2117
- ...pageResponse.scrollProps || {}
2118
- };
2119
- }
2120
- if (page.hasOnceProps()) {
2121
- pageResponse.onceProps = {
2122
- ...page.get().onceProps || {},
2123
- ...pageResponse.onceProps || {}
2124
- };
2125
- }
2126
- pageResponse.flash = {
2127
- ...page.get().flash,
2128
- ...this.requestParams.isDeferredPropsRequest() ? {} : pageResponse.flash
2129
- };
2130
- const currentOriginalDeferred = page.get().initialDeferredProps;
2131
- if (currentOriginalDeferred && Object.keys(currentOriginalDeferred).length > 0) {
2132
- pageResponse.initialDeferredProps = currentOriginalDeferred;
2133
- }
2134
- }
2135
- mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) {
2136
- const items = Array.isArray(existingItems) ? existingItems : [];
2137
- const matchingKey = matchPropsOn.find((key) => {
2138
- const keyPath = key.split(".").slice(0, -1).join(".");
2139
- return keyPath === matchProp;
2140
- });
2141
- if (!matchingKey) {
2142
- return shouldAppend ? [...items, ...newItems] : [...newItems, ...items];
2143
- }
2144
- const uniqueProperty = matchingKey.split(".").pop() || "";
2145
- const newItemsMap = /* @__PURE__ */ new Map();
2146
- newItems.forEach((item) => {
2147
- if (this.hasUniqueProperty(item, uniqueProperty)) {
2148
- newItemsMap.set(item[uniqueProperty], item);
2149
- }
2150
- });
2151
- return shouldAppend ? this.appendWithMatching(items, newItems, newItemsMap, uniqueProperty) : this.prependWithMatching(items, newItems, newItemsMap, uniqueProperty);
2152
- }
2153
- appendWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) {
2154
- const updatedExisting = existingItems.map((item) => {
2155
- if (this.hasUniqueProperty(item, uniqueProperty) && newItemsMap.has(item[uniqueProperty])) {
2156
- return newItemsMap.get(item[uniqueProperty]);
2157
- }
2158
- return item;
2159
- });
2160
- const newItemsToAdd = newItems.filter((item) => {
2161
- if (!this.hasUniqueProperty(item, uniqueProperty)) {
2162
- return true;
2163
- }
2164
- return !existingItems.some(
2165
- (existing) => this.hasUniqueProperty(existing, uniqueProperty) && existing[uniqueProperty] === item[uniqueProperty]
2166
- );
2167
- });
2168
- return [...updatedExisting, ...newItemsToAdd];
2169
- }
2170
- prependWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) {
2171
- const untouchedExisting = existingItems.filter((item) => {
2172
- if (this.hasUniqueProperty(item, uniqueProperty)) {
2173
- return !newItemsMap.has(item[uniqueProperty]);
2174
- }
2175
- return true;
2176
- });
2177
- return [...newItems, ...untouchedExisting];
2178
- }
2179
- hasUniqueProperty(item, property) {
2180
- return item && typeof item === "object" && property in item;
2181
- }
2182
- async setRememberedState(pageResponse) {
2183
- const rememberedState = await history.getState(history.rememberedState, {});
2184
- if (this.requestParams.all().preserveState && rememberedState && pageResponse.component === page.get().component) {
2185
- pageResponse.rememberedState = rememberedState;
2186
- }
2187
- }
2188
- getScopedErrors(errors) {
2189
- if (!this.requestParams.all().errorBag) {
2190
- return errors;
2191
- }
2192
- return errors[this.requestParams.all().errorBag || ""] || {};
2193
- }
2194
- };
2195
-
2196
- // src/request.ts
2197
- var Request = class _Request {
2198
- constructor(params, page2) {
2199
- this.page = page2;
2200
- this.requestHasFinished = false;
2201
- this.requestParams = RequestParams.create(params);
2202
- this.cancelToken = new AbortController();
2203
- }
2204
- static create(params, page2) {
2205
- return new _Request(params, page2);
2206
- }
2207
- isPrefetch() {
2208
- return this.requestParams.isPrefetch();
2209
- }
2210
- async send() {
2211
- this.requestParams.onCancelToken(() => this.cancel({ cancelled: true }));
2212
- fireStartEvent(this.requestParams.all());
2213
- this.requestParams.onStart();
2214
- if (this.requestParams.all().prefetch) {
2215
- this.requestParams.onPrefetching();
2216
- firePrefetchingEvent(this.requestParams.all());
2217
- }
2218
- const originallyPrefetch = this.requestParams.all().prefetch;
2219
- return axios({
2220
- method: this.requestParams.all().method,
2221
- url: urlWithoutHash(this.requestParams.all().url).href,
2222
- data: this.requestParams.data(),
2223
- params: this.requestParams.queryParams(),
2224
- signal: this.cancelToken.signal,
2225
- headers: this.getHeaders(),
2226
- onUploadProgress: this.onProgress.bind(this),
2227
- // Why text? This allows us to delay JSON.parse until we're ready to use the response,
2228
- // helps with performance particularly on large responses + history encryption
2229
- responseType: "text"
2230
- }).then((response) => {
2231
- this.response = Response.create(this.requestParams, response, this.page);
2232
- return this.response.handle();
2233
- }).catch((error) => {
2234
- if (error?.response) {
2235
- this.response = Response.create(this.requestParams, error.response, this.page);
2236
- return this.response.handle();
2237
- }
2238
- return Promise.reject(error);
2239
- }).catch((error) => {
2240
- if (axios.isCancel(error)) {
2241
- return;
2242
- }
2243
- if (fireExceptionEvent(error)) {
2244
- if (originallyPrefetch) {
2245
- this.requestParams.onPrefetchError(error);
2246
- }
2247
- return Promise.reject(error);
2248
- }
2249
- }).finally(() => {
2250
- this.finish();
2251
- if (originallyPrefetch && this.response) {
2252
- this.requestParams.onPrefetchResponse(this.response);
2253
- }
2254
- });
2255
- }
2256
- finish() {
2257
- if (this.requestParams.wasCancelledAtAll()) {
2258
- return;
2259
- }
2260
- this.requestParams.markAsFinished();
2261
- this.fireFinishEvents();
2262
- }
2263
- fireFinishEvents() {
2264
- if (this.requestHasFinished) {
2265
- return;
2266
- }
2267
- this.requestHasFinished = true;
2268
- fireFinishEvent(this.requestParams.all());
2269
- this.requestParams.onFinish();
2270
- }
2271
- cancel({ cancelled = false, interrupted = false }) {
2272
- if (this.requestHasFinished) {
2273
- return;
2274
- }
2275
- this.cancelToken.abort();
2276
- this.requestParams.markAsCancelled({ cancelled, interrupted });
2277
- this.fireFinishEvents();
2278
- }
2279
- onProgress(progress3) {
2280
- if (this.requestParams.data() instanceof FormData) {
2281
- progress3.percentage = progress3.progress ? Math.round(progress3.progress * 100) : 0;
2282
- fireProgressEvent(progress3);
2283
- this.requestParams.all().onProgress(progress3);
2284
- }
2285
- }
2286
- getHeaders() {
2287
- const headers = {
2288
- ...this.requestParams.headers(),
2289
- Accept: "text/html, application/xhtml+xml",
2290
- "X-Requested-With": "XMLHttpRequest",
2291
- "X-Inertia": true
2292
- };
2293
- const page2 = page.get();
2294
- if (page2.version) {
2295
- headers["X-Inertia-Version"] = page2.version;
2296
- }
2297
- const onceProps = Object.entries(page2.onceProps || {}).filter(([, onceProp]) => {
2298
- if (page2.props[onceProp.prop] === void 0) {
2299
- return false;
2300
- }
2301
- return !onceProp.expiresAt || onceProp.expiresAt > Date.now();
2302
- }).map(([key]) => key);
2303
- if (onceProps.length > 0) {
2304
- headers["X-Inertia-Except-Once-Props"] = onceProps.join(",");
2305
- }
2306
- return headers;
2307
- }
2308
- };
2309
-
2310
- // src/requestStream.ts
2311
- var RequestStream = class {
2312
- constructor({ maxConcurrent, interruptible }) {
2313
- this.requests = [];
2314
- this.maxConcurrent = maxConcurrent;
2315
- this.interruptible = interruptible;
2316
- }
2317
- send(request) {
2318
- this.requests.push(request);
2319
- request.send().then(() => {
2320
- this.requests = this.requests.filter((r) => r !== request);
2321
- });
2322
- }
2323
- interruptInFlight() {
2324
- this.cancel({ interrupted: true }, false);
2325
- }
2326
- cancelInFlight({ prefetch = true } = {}) {
2327
- this.requests.filter((request) => prefetch || !request.isPrefetch()).forEach((request) => request.cancel({ cancelled: true }));
2328
- }
2329
- cancel({ cancelled = false, interrupted = false } = {}, force = false) {
2330
- if (!force && !this.shouldCancel()) {
2331
- return;
2332
- }
2333
- const request = this.requests.shift();
2334
- request?.cancel({ cancelled, interrupted });
2335
- }
2336
- shouldCancel() {
2337
- return this.interruptible && this.requests.length >= this.maxConcurrent;
2338
- }
2339
- };
2340
-
2341
- // src/router.ts
2342
- var Router = class {
2343
- constructor() {
2344
- this.syncRequestStream = new RequestStream({
2345
- maxConcurrent: 1,
2346
- interruptible: true
2347
- });
2348
- this.asyncRequestStream = new RequestStream({
2349
- maxConcurrent: Infinity,
2350
- interruptible: false
2351
- });
2352
- this.clientVisitQueue = new Queue();
2353
- }
2354
- init({
2355
- initialPage,
2356
- resolveComponent,
2357
- swapComponent,
2358
- onFlash
2359
- }) {
2360
- page.init({
2361
- initialPage,
2362
- resolveComponent,
2363
- swapComponent,
2364
- onFlash
2365
- });
2366
- InitialVisit.handle();
2367
- eventHandler.init();
2368
- eventHandler.on("missingHistoryItem", () => {
2369
- if (typeof window !== "undefined") {
2370
- this.visit(window.location.href, { preserveState: true, preserveScroll: true, replace: true });
2371
- }
2372
- });
2373
- eventHandler.on("loadDeferredProps", (deferredProps) => {
2374
- this.loadDeferredProps(deferredProps);
2375
- });
2376
- eventHandler.on("historyQuotaExceeded", (url) => {
2377
- window.location.href = url;
2378
- });
2379
- }
2380
- get(url, data = {}, options = {}) {
2381
- return this.visit(url, { ...options, method: "get", data });
2382
- }
2383
- post(url, data = {}, options = {}) {
2384
- return this.visit(url, { preserveState: true, ...options, method: "post", data });
2385
- }
2386
- put(url, data = {}, options = {}) {
2387
- return this.visit(url, { preserveState: true, ...options, method: "put", data });
2388
- }
2389
- patch(url, data = {}, options = {}) {
2390
- return this.visit(url, { preserveState: true, ...options, method: "patch", data });
2391
- }
2392
- delete(url, options = {}) {
2393
- return this.visit(url, { preserveState: true, ...options, method: "delete" });
2394
- }
2395
- reload(options = {}) {
2396
- return this.doReload(options);
2397
- }
2398
- doReload(options = {}) {
2399
- if (typeof window === "undefined") {
2400
- return;
2401
- }
2402
- return this.visit(window.location.href, {
2403
- ...options,
2404
- preserveScroll: true,
2405
- preserveState: true,
2406
- async: true,
2407
- headers: {
2408
- ...options.headers || {},
2409
- "Cache-Control": "no-cache"
2410
- }
2411
- });
2412
- }
2413
- remember(data, key = "default") {
2414
- history.remember(data, key);
2415
- }
2416
- restore(key = "default") {
2417
- return history.restore(key);
2418
- }
2419
- on(type, callback) {
2420
- if (typeof window === "undefined") {
2421
- return () => {
2422
- };
2423
- }
2424
- return eventHandler.onGlobalEvent(type, callback);
2425
- }
2426
- /**
2427
- * @deprecated Use cancelAll() instead.
2428
- */
2429
- cancel() {
2430
- this.syncRequestStream.cancelInFlight();
2431
- }
2432
- cancelAll({ async = true, prefetch = true, sync = true } = {}) {
2433
- if (async) {
2434
- this.asyncRequestStream.cancelInFlight({ prefetch });
2435
- }
2436
- if (sync) {
2437
- this.syncRequestStream.cancelInFlight();
2438
- }
2439
- }
2440
- poll(interval, requestOptions = {}, options = {}) {
2441
- return polls.add(interval, () => this.reload(requestOptions), {
2442
- autoStart: options.autoStart ?? true,
2443
- keepAlive: options.keepAlive ?? false
2444
- });
2445
- }
2446
- visit(href, options = {}) {
2447
- const visit = this.getPendingVisit(href, {
2448
- ...options,
2449
- showProgress: options.showProgress ?? !options.async
2450
- });
2451
- const events = this.getVisitEvents(options);
2452
- if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) {
2453
- return;
2454
- }
2455
- const currentPageUrl = hrefToUrl(page.get().url);
2456
- const isPartialReload = visit.only.length > 0 || visit.except.length > 0 || visit.reset.length > 0;
2457
- const isSamePage = isPartialReload ? isSameUrlWithoutQueryOrHash(visit.url, currentPageUrl) : isSameUrlWithoutHash(visit.url, currentPageUrl);
2458
- if (!isSamePage) {
2459
- this.asyncRequestStream.cancelInFlight({ prefetch: false });
2460
- }
2461
- if (!visit.async) {
2462
- this.syncRequestStream.interruptInFlight();
2463
- }
2464
- if (!page.isCleared() && !visit.preserveUrl) {
2465
- Scroll.save();
2466
- }
2467
- const requestParams = {
2468
- ...visit,
2469
- ...events
2470
- };
2471
- const prefetched = prefetchedRequests.get(requestParams);
2472
- if (prefetched) {
2473
- progress.reveal(prefetched.inFlight);
2474
- prefetchedRequests.use(prefetched, requestParams);
2475
- } else {
2476
- progress.reveal(true);
2477
- const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream;
2478
- requestStream.send(Request.create(requestParams, page.get()));
2479
- }
2480
- }
2481
- getCached(href, options = {}) {
2482
- return prefetchedRequests.findCached(this.getPrefetchParams(href, options));
2483
- }
2484
- flush(href, options = {}) {
2485
- prefetchedRequests.remove(this.getPrefetchParams(href, options));
2486
- }
2487
- flushAll() {
2488
- prefetchedRequests.removeAll();
2489
- }
2490
- flushByCacheTags(tags) {
2491
- prefetchedRequests.removeByTags(Array.isArray(tags) ? tags : [tags]);
2492
- }
2493
- getPrefetching(href, options = {}) {
2494
- return prefetchedRequests.findInFlight(this.getPrefetchParams(href, options));
2495
- }
2496
- prefetch(href, options = {}, prefetchOptions = {}) {
2497
- const method = options.method ?? (isUrlMethodPair(href) ? href.method : "get");
2498
- if (method !== "get") {
2499
- throw new Error("Prefetch requests must use the GET method");
2500
- }
2501
- const visit = this.getPendingVisit(href, {
2502
- ...options,
2503
- async: true,
2504
- showProgress: false,
2505
- prefetch: true,
2506
- viewTransition: false
2507
- });
2508
- const visitUrl = visit.url.origin + visit.url.pathname + visit.url.search;
2509
- const currentUrl = window.location.origin + window.location.pathname + window.location.search;
2510
- if (visitUrl === currentUrl) {
2511
- return;
2512
- }
2513
- const events = this.getVisitEvents(options);
2514
- if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) {
2515
- return;
2516
- }
2517
- progress.hide();
2518
- this.asyncRequestStream.interruptInFlight();
2519
- const requestParams = {
2520
- ...visit,
2521
- ...events
2522
- };
2523
- const ensureCurrentPageIsSet = () => {
2524
- return new Promise((resolve) => {
2525
- const checkIfPageIsDefined = () => {
2526
- if (page.get()) {
2527
- resolve();
2528
- } else {
2529
- setTimeout(checkIfPageIsDefined, 50);
2530
- }
2531
- };
2532
- checkIfPageIsDefined();
2533
- });
2534
- };
2535
- ensureCurrentPageIsSet().then(() => {
2536
- prefetchedRequests.add(
2537
- requestParams,
2538
- (params) => {
2539
- this.asyncRequestStream.send(Request.create(params, page.get()));
2540
- },
2541
- {
2542
- cacheFor: config.get("prefetch.cacheFor"),
2543
- cacheTags: [],
2544
- ...prefetchOptions
2545
- }
2546
- );
2547
- });
2548
- }
2549
- clearHistory() {
2550
- history.clear();
2551
- }
2552
- decryptHistory() {
2553
- return history.decrypt();
2554
- }
2555
- resolveComponent(component) {
2556
- return page.resolve(component);
2557
- }
2558
- replace(params) {
2559
- this.clientVisit(params, { replace: true });
2560
- }
2561
- replaceProp(name, value, options) {
2562
- this.replace({
2563
- preserveScroll: true,
2564
- preserveState: true,
2565
- props(currentProps) {
2566
- const newValue = typeof value === "function" ? value(get3(currentProps, name), currentProps) : value;
2567
- return set3(cloneDeep3(currentProps), name, newValue);
2568
- },
2569
- ...options || {}
2570
- });
2571
- }
2572
- appendToProp(name, value, options) {
2573
- this.replaceProp(
2574
- name,
2575
- (currentValue, currentProps) => {
2576
- const newValue = typeof value === "function" ? value(currentValue, currentProps) : value;
2577
- if (!Array.isArray(currentValue)) {
2578
- currentValue = currentValue !== void 0 ? [currentValue] : [];
2579
- }
2580
- return [...currentValue, newValue];
2581
- },
2582
- options
2583
- );
2584
- }
2585
- prependToProp(name, value, options) {
2586
- this.replaceProp(
2587
- name,
2588
- (currentValue, currentProps) => {
2589
- const newValue = typeof value === "function" ? value(currentValue, currentProps) : value;
2590
- if (!Array.isArray(currentValue)) {
2591
- currentValue = currentValue !== void 0 ? [currentValue] : [];
2592
- }
2593
- return [newValue, ...currentValue];
2594
- },
2595
- options
2596
- );
2597
- }
2598
- push(params) {
2599
- this.clientVisit(params);
2600
- }
2601
- flash(keyOrData, value) {
2602
- const current = page.get().flash;
2603
- let flash;
2604
- if (typeof keyOrData === "function") {
2605
- flash = keyOrData(current);
2606
- } else if (typeof keyOrData === "string") {
2607
- flash = { ...current, [keyOrData]: value };
2608
- } else if (keyOrData && Object.keys(keyOrData).length) {
2609
- flash = { ...current, ...keyOrData };
2610
- } else {
2611
- return;
2612
- }
2613
- page.setFlash(flash);
2614
- if (Object.keys(flash).length) {
2615
- fireFlashEvent(flash);
2616
- }
2617
- }
2618
- clientVisit(params, { replace = false } = {}) {
2619
- this.clientVisitQueue.add(() => this.performClientVisit(params, { replace }));
2620
- }
2621
- performClientVisit(params, { replace = false } = {}) {
2622
- const current = page.get();
2623
- const onceProps = typeof params.props === "function" ? Object.fromEntries(
2624
- Object.values(current.onceProps ?? {}).map((onceProp) => [onceProp.prop, current.props[onceProp.prop]])
2625
- ) : {};
2626
- const props = typeof params.props === "function" ? params.props(current.props, onceProps) : params.props ?? current.props;
2627
- const flash = typeof params.flash === "function" ? params.flash(current.flash) : params.flash;
2628
- const { viewTransition, onError, onFinish, onFlash, onSuccess, ...pageParams } = params;
2629
- const page2 = {
2630
- ...current,
2631
- ...pageParams,
2632
- flash: flash ?? {},
2633
- props
2634
- };
2635
- const preserveScroll = RequestParams.resolvePreserveOption(params.preserveScroll ?? false, page2);
2636
- const preserveState = RequestParams.resolvePreserveOption(params.preserveState ?? false, page2);
2637
- return page.set(page2, {
2638
- replace,
2639
- preserveScroll,
2640
- preserveState,
2641
- viewTransition
2642
- }).then(() => {
2643
- const currentFlash = page.get().flash;
2644
- if (Object.keys(currentFlash).length > 0) {
2645
- fireFlashEvent(currentFlash);
2646
- onFlash?.(currentFlash);
2647
- }
2648
- const errors = page.get().props.errors || {};
2649
- if (Object.keys(errors).length === 0) {
2650
- onSuccess?.(page.get());
2651
- return;
2652
- }
2653
- const scopedErrors = params.errorBag ? errors[params.errorBag || ""] || {} : errors;
2654
- onError?.(scopedErrors);
2655
- }).finally(() => onFinish?.(params));
2656
- }
2657
- getPrefetchParams(href, options) {
2658
- return {
2659
- ...this.getPendingVisit(href, {
2660
- ...options,
2661
- async: true,
2662
- showProgress: false,
2663
- prefetch: true,
2664
- viewTransition: false
2665
- }),
2666
- ...this.getVisitEvents(options)
2667
- };
2668
- }
2669
- getPendingVisit(href, options, pendingVisitOptions = {}) {
2670
- if (isUrlMethodPair(href)) {
2671
- const urlMethodPair = href;
2672
- href = urlMethodPair.url;
2673
- options.method = options.method ?? urlMethodPair.method;
2674
- }
2675
- const defaultVisitOptionsCallback = config.get("visitOptions");
2676
- const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep3(options)) || {} : {};
2677
- const mergedOptions = {
2678
- method: "get",
2679
- data: {},
2680
- replace: false,
2681
- preserveScroll: false,
2682
- preserveState: false,
2683
- only: [],
2684
- except: [],
2685
- headers: {},
2686
- errorBag: "",
2687
- forceFormData: false,
2688
- queryStringArrayFormat: "brackets",
2689
- async: false,
2690
- showProgress: true,
2691
- fresh: false,
2692
- reset: [],
2693
- preserveUrl: false,
2694
- prefetch: false,
2695
- invalidateCacheTags: [],
2696
- viewTransition: false,
2697
- ...options,
2698
- ...configuredOptions
2699
- };
2700
- const [url, _data] = transformUrlAndData(
2701
- href,
2702
- mergedOptions.data,
2703
- mergedOptions.method,
2704
- mergedOptions.forceFormData,
2705
- mergedOptions.queryStringArrayFormat
2706
- );
2707
- const visit = {
2708
- cancelled: false,
2709
- completed: false,
2710
- interrupted: false,
2711
- ...mergedOptions,
2712
- ...pendingVisitOptions,
2713
- url,
2714
- data: _data
2715
- };
2716
- if (visit.prefetch) {
2717
- visit.headers["Purpose"] = "prefetch";
2718
- }
2719
- return visit;
2720
- }
2721
- getVisitEvents(options) {
2722
- return {
2723
- onCancelToken: options.onCancelToken || (() => {
2724
- }),
2725
- onBefore: options.onBefore || (() => {
2726
- }),
2727
- onBeforeUpdate: options.onBeforeUpdate || (() => {
2728
- }),
2729
- onStart: options.onStart || (() => {
2730
- }),
2731
- onProgress: options.onProgress || (() => {
2732
- }),
2733
- onFinish: options.onFinish || (() => {
2734
- }),
2735
- onCancel: options.onCancel || (() => {
2736
- }),
2737
- onSuccess: options.onSuccess || (() => {
2738
- }),
2739
- onError: options.onError || (() => {
2740
- }),
2741
- onFlash: options.onFlash || (() => {
2742
- }),
2743
- onPrefetched: options.onPrefetched || (() => {
2744
- }),
2745
- onPrefetching: options.onPrefetching || (() => {
2746
- })
2747
- };
2748
- }
2749
- loadDeferredProps(deferred) {
2750
- if (deferred) {
2751
- Object.entries(deferred).forEach(([_, group]) => {
2752
- this.doReload({ only: group, deferredProps: true });
2753
- });
2754
- }
2755
- }
2756
- };
2757
-
2758
- // src/useFormUtils.ts
2759
- var UseFormUtils = class {
2760
- /**
2761
- * Creates a callback that returns a UrlMethodPair.
2762
- *
2763
- * createWayfinderCallback(urlMethodPair)
2764
- * createWayfinderCallback(method, url)
2765
- * createWayfinderCallback(() => urlMethodPair)
2766
- * createWayfinderCallback(() => method, () => url)
2767
- */
2768
- static createWayfinderCallback(...args) {
2769
- return () => {
2770
- if (args.length === 1) {
2771
- return isUrlMethodPair(args[0]) ? args[0] : args[0]();
2772
- }
2773
- return {
2774
- method: typeof args[0] === "function" ? args[0]() : args[0],
2775
- url: typeof args[1] === "function" ? args[1]() : args[1]
2776
- };
2777
- };
2778
- }
2779
- /**
2780
- * Parses all useForm() arguments into { rememberKey, data, precognitionEndpoint }.
2781
- *
2782
- * useForm()
2783
- * useForm(data)
2784
- * useForm(rememberKey, data)
2785
- * useForm(method, url, data)
2786
- * useForm(urlMethodPair, data)
2787
- *
2788
- */
2789
- static parseUseFormArguments(...args) {
2790
- if (args.length === 0) {
2791
- return {
2792
- rememberKey: null,
2793
- data: {},
2794
- precognitionEndpoint: null
2795
- };
2796
- }
2797
- if (args.length === 1) {
2798
- return {
2799
- rememberKey: null,
2800
- data: args[0],
2801
- precognitionEndpoint: null
2802
- };
2803
- }
2804
- if (args.length === 2) {
2805
- if (typeof args[0] === "string") {
2806
- return {
2807
- rememberKey: args[0],
2808
- data: args[1],
2809
- precognitionEndpoint: null
2810
- };
2811
- }
2812
- return {
2813
- rememberKey: null,
2814
- data: args[1],
2815
- precognitionEndpoint: this.createWayfinderCallback(args[0])
2816
- };
2817
- }
2818
- return {
2819
- rememberKey: null,
2820
- data: args[2],
2821
- precognitionEndpoint: this.createWayfinderCallback(args[0], args[1])
2822
- };
2823
- }
2824
- /**
2825
- * Parses all submission arguments into { method, url, options }.
2826
- * It uses the Precognition endpoint if no explicit method/url are provided.
2827
- *
2828
- * form.submit(method, url)
2829
- * form.submit(method, url, options)
2830
- * form.submit(urlMethodPair)
2831
- * form.submit(urlMethodPair, options)
2832
- * form.submit()
2833
- * form.submit(options)
2834
- */
2835
- static parseSubmitArguments(args, precognitionEndpoint) {
2836
- if (args.length === 3 || args.length === 2 && typeof args[0] === "string") {
2837
- return { method: args[0], url: args[1], options: args[2] ?? {} };
2838
- }
2839
- if (isUrlMethodPair(args[0])) {
2840
- return { ...args[0], options: args[1] ?? {} };
2841
- }
2842
- return { ...precognitionEndpoint(), options: args[0] ?? {} };
2843
- }
2844
- /**
2845
- * Merges headers into the Precognition validate() arguments.
2846
- */
2847
- static mergeHeadersForValidation(field, config2, headers) {
2848
- const merge = (config3) => {
2849
- config3.headers = {
2850
- ...headers ?? {},
2851
- ...config3.headers ?? {}
2852
- };
2853
- return config3;
2854
- };
2855
- if (field && typeof field === "object" && !("target" in field)) {
2856
- field = merge(field);
2857
- } else if (config2 && typeof config2 === "object") {
2858
- config2 = merge(config2);
2859
- } else if (typeof field === "string") {
2860
- config2 = merge(config2 ?? {});
2861
- } else {
2862
- field = merge(field ?? {});
2863
- }
2864
- return [field, config2];
2865
- }
2866
- };
2867
-
2868
- // src/formObject.ts
2869
- import { get as get4, set as set4 } from "lodash-es";
2870
- function undotKey(key) {
2871
- if (!key.includes(".")) {
2872
- return key;
2873
- }
2874
- const transformSegment = (segment) => {
2875
- if (segment.startsWith("[") && segment.endsWith("]")) {
2876
- return segment;
2877
- }
2878
- return segment.split(".").reduce((result, part, index) => index === 0 ? part : `${result}[${part}]`);
2879
- };
2880
- return key.replace(/\\\./g, "__ESCAPED_DOT__").split(/(\[[^\]]*\])/).filter(Boolean).map(transformSegment).join("").replace(/__ESCAPED_DOT__/g, ".");
2881
- }
2882
- function parseKey(key) {
2883
- const path = [];
2884
- const pattern = /([^\[\]]+)|\[(\d*)\]/g;
2885
- let match;
2886
- while ((match = pattern.exec(key)) !== null) {
2887
- if (match[1] !== void 0) {
2888
- path.push(match[1]);
2889
- } else if (match[2] !== void 0) {
2890
- path.push(match[2] === "" ? "" : Number(match[2]));
2891
- }
2892
- }
2893
- return path;
2894
- }
2895
- function setNestedObject(obj, path, value) {
2896
- let current = obj;
2897
- for (let i = 0; i < path.length - 1; i++) {
2898
- if (!(path[i] in current)) {
2899
- current[path[i]] = {};
2900
- }
2901
- current = current[path[i]];
2902
- }
2903
- current[path[path.length - 1]] = value;
2904
- }
2905
- function objectHasSequentialNumericKeys(value) {
2906
- const keys = Object.keys(value);
2907
- const numericKeys = keys.filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b);
2908
- return keys.length === numericKeys.length && numericKeys.length > 0 && numericKeys[0] === 0 && numericKeys.every((n, i) => n === i);
2909
- }
2910
- function convertSequentialObjectsToArrays(value) {
2911
- if (Array.isArray(value)) {
2912
- return value.map(convertSequentialObjectsToArrays);
2913
- }
2914
- if (typeof value !== "object" || value === null || isFile(value)) {
2915
- return value;
2916
- }
2917
- if (objectHasSequentialNumericKeys(value)) {
2918
- const result2 = [];
2919
- for (let i = 0; i < Object.keys(value).length; i++) {
2920
- result2[i] = convertSequentialObjectsToArrays(value[i]);
2921
- }
2922
- return result2;
2923
- }
2924
- const result = {};
2925
- for (const key in value) {
2926
- result[key] = convertSequentialObjectsToArrays(value[key]);
2927
- }
2928
- return result;
2929
- }
2930
- function formDataToObject(source) {
2931
- const form = {};
2932
- for (const [key, value] of source.entries()) {
2933
- if (value instanceof File && value.size === 0 && value.name === "") {
2934
- continue;
2935
- }
2936
- const path = parseKey(undotKey(key));
2937
- if (path[path.length - 1] === "") {
2938
- const arrayPath = path.slice(0, -1);
2939
- const existing = get4(form, arrayPath);
2940
- if (Array.isArray(existing)) {
2941
- existing.push(value);
2942
- } else if (existing && typeof existing === "object" && !isFile(existing)) {
2943
- const numericKeys = Object.keys(existing).filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b);
2944
- set4(form, arrayPath, numericKeys.length > 0 ? [...numericKeys.map((k) => existing[k]), value] : [value]);
2945
- } else {
2946
- set4(form, arrayPath, [value]);
2947
- }
2948
- continue;
2949
- }
2950
- setNestedObject(form, path.map(String), value);
2951
- }
2952
- return convertSequentialObjectsToArrays(form);
2953
- }
2954
-
2955
- // src/head.ts
2956
- var Renderer = {
2957
- preferredAttribute() {
2958
- return config.get("future.useDataInertiaHeadAttribute") ? "data-inertia" : "inertia";
2959
- },
2960
- buildDOMElement(tag) {
2961
- const template = document.createElement("template");
2962
- template.innerHTML = tag;
2963
- const node = template.content.firstChild;
2964
- if (!tag.startsWith("<script ")) {
2965
- return node;
2966
- }
2967
- const script = document.createElement("script");
2968
- script.innerHTML = node.innerHTML;
2969
- node.getAttributeNames().forEach((name) => {
2970
- script.setAttribute(name, node.getAttribute(name) || "");
2971
- });
2972
- return script;
2973
- },
2974
- isInertiaManagedElement(element) {
2975
- return element.nodeType === Node.ELEMENT_NODE && element.getAttribute(this.preferredAttribute()) !== null;
2976
- },
2977
- findMatchingElementIndex(element, elements) {
2978
- const attribute = this.preferredAttribute();
2979
- const key = element.getAttribute(attribute);
2980
- if (key !== null) {
2981
- return elements.findIndex((element2) => element2.getAttribute(attribute) === key);
2982
- }
2983
- return -1;
2984
- },
2985
- update: debounce(function(elements) {
2986
- const sourceElements = elements.map((element) => this.buildDOMElement(element));
2987
- const targetElements = Array.from(document.head.childNodes).filter(
2988
- (element) => this.isInertiaManagedElement(element)
2989
- );
2990
- targetElements.forEach((targetElement) => {
2991
- const index = this.findMatchingElementIndex(targetElement, sourceElements);
2992
- if (index === -1) {
2993
- targetElement?.parentNode?.removeChild(targetElement);
2994
- return;
2995
- }
2996
- const sourceElement = sourceElements.splice(index, 1)[0];
2997
- if (sourceElement && !targetElement.isEqualNode(sourceElement)) {
2998
- targetElement?.parentNode?.replaceChild(sourceElement, targetElement);
2999
- }
3000
- });
3001
- sourceElements.forEach((element) => document.head.appendChild(element));
3002
- }, 1)
3003
- };
3004
- function createHeadManager(isServer3, titleCallback, onUpdate) {
3005
- const states = {};
3006
- let lastProviderId = 0;
3007
- function connect() {
3008
- const id = lastProviderId += 1;
3009
- states[id] = [];
3010
- return id.toString();
3011
- }
3012
- function disconnect(id) {
3013
- if (id === null || Object.keys(states).indexOf(id) === -1) {
3014
- return;
3015
- }
3016
- delete states[id];
3017
- commit();
3018
- }
3019
- function reconnect(id) {
3020
- if (Object.keys(states).indexOf(id) === -1) {
3021
- states[id] = [];
3022
- }
3023
- }
3024
- function update(id, elements = []) {
3025
- if (id !== null && Object.keys(states).indexOf(id) > -1) {
3026
- states[id] = elements;
3027
- }
3028
- commit();
3029
- }
3030
- function collect() {
3031
- const title = titleCallback("");
3032
- const attribute = Renderer.preferredAttribute();
3033
- const defaults = {
3034
- ...title ? { title: `<title ${attribute}="">${title}</title>` } : {}
3035
- };
3036
- const elements = Object.values(states).reduce((carry, elements2) => carry.concat(elements2), []).reduce((carry, element) => {
3037
- if (element.indexOf("<") === -1) {
3038
- return carry;
3039
- }
3040
- if (element.indexOf("<title ") === 0) {
3041
- const title2 = element.match(/(<title [^>]+>)(.*?)(<\/title>)/);
3042
- carry.title = title2 ? `${title2[1]}${titleCallback(title2[2])}${title2[3]}` : element;
3043
- return carry;
3044
- }
3045
- const match = element.match(attribute === "inertia" ? / inertia="[^"]+"/ : / data-inertia="[^"]+"/);
3046
- if (match) {
3047
- carry[match[0]] = element;
3048
- } else {
3049
- carry[Object.keys(carry).length] = element;
3050
- }
3051
- return carry;
3052
- }, defaults);
3053
- return Object.values(elements);
3054
- }
3055
- function commit() {
3056
- isServer3 ? onUpdate(collect()) : Renderer.update(collect());
3057
- }
3058
- commit();
3059
- return {
3060
- forceUpdate: commit,
3061
- createProvider: function() {
3062
- const id = connect();
3063
- return {
3064
- preferredAttribute: Renderer.preferredAttribute,
3065
- reconnect: () => reconnect(id),
3066
- update: (elements) => update(id, elements),
3067
- disconnect: () => disconnect(id)
3068
- };
3069
- }
3070
- };
3071
- }
3072
-
3073
- // src/infiniteScroll/data.ts
3074
- var MERGE_INTENT_HEADER = "X-Inertia-Infinite-Scroll-Merge-Intent";
3075
- var useInfiniteScrollData = (options) => {
3076
- const getScrollPropFromCurrentPage = () => {
3077
- const scrollProp = page.get().scrollProps?.[options.getPropName()];
3078
- if (scrollProp) {
3079
- return scrollProp;
3080
- }
3081
- throw new Error(`The page object does not contain a scroll prop named "${options.getPropName()}".`);
3082
- };
3083
- const state = {
3084
- component: null,
3085
- loading: false,
3086
- previousPage: null,
3087
- nextPage: null,
3088
- lastLoadedPage: null,
3089
- requestCount: 0
3090
- };
3091
- const resetState = () => {
3092
- const scrollProp = getScrollPropFromCurrentPage();
3093
- state.component = page.get().component;
3094
- state.loading = false;
3095
- state.previousPage = scrollProp.previousPage;
3096
- state.nextPage = scrollProp.nextPage;
3097
- state.lastLoadedPage = scrollProp.currentPage;
3098
- state.requestCount = 0;
3099
- };
3100
- const getRememberKey = () => `inertia:infinite-scroll-data:${options.getPropName()}`;
3101
- if (typeof window !== "undefined") {
3102
- resetState();
3103
- const rememberedState = router.restore(getRememberKey());
3104
- if (rememberedState && typeof rememberedState === "object" && rememberedState.lastLoadedPage === getScrollPropFromCurrentPage().currentPage) {
3105
- state.previousPage = rememberedState.previousPage;
3106
- state.nextPage = rememberedState.nextPage;
3107
- state.lastLoadedPage = rememberedState.lastLoadedPage;
3108
- state.requestCount = rememberedState.requestCount || 0;
3109
- }
3110
- }
3111
- const removeEventListener = router.on("success", (event) => {
3112
- if (state.component === event.detail.page.component && getScrollPropFromCurrentPage().reset) {
3113
- resetState();
3114
- options.onReset?.();
3115
- }
3116
- });
3117
- const getScrollPropKeyForSide = (side) => {
3118
- return side === "next" ? "nextPage" : "previousPage";
3119
- };
3120
- const findPageToLoad = (side) => {
3121
- const pagePropName = getScrollPropKeyForSide(side);
3122
- return state[pagePropName];
3123
- };
3124
- const syncStateOnSuccess = (side) => {
3125
- const scrollProp = getScrollPropFromCurrentPage();
3126
- const paginationProp = getScrollPropKeyForSide(side);
3127
- state.lastLoadedPage = scrollProp.currentPage;
3128
- state[paginationProp] = scrollProp[paginationProp];
3129
- state.requestCount += 1;
3130
- router.remember(
3131
- {
3132
- previousPage: state.previousPage,
3133
- nextPage: state.nextPage,
3134
- lastLoadedPage: state.lastLoadedPage,
3135
- requestCount: state.requestCount
3136
- },
3137
- getRememberKey()
3138
- );
3139
- };
3140
- const getPageName = () => getScrollPropFromCurrentPage().pageName;
3141
- const getRequestCount = () => state.requestCount;
3142
- const fetchPage = (side, reloadOptions = {}) => {
3143
- const page2 = findPageToLoad(side);
3144
- if (state.loading || page2 === null) {
3145
- return;
3146
- }
3147
- state.loading = true;
3148
- router.reload({
3149
- ...reloadOptions,
3150
- data: { [getPageName()]: page2 },
3151
- only: [options.getPropName()],
3152
- preserveUrl: true,
3153
- // we handle URL updates manually via useInfiniteScrollQueryString()
3154
- headers: {
3155
- [MERGE_INTENT_HEADER]: side === "previous" ? "prepend" : "append",
3156
- ...reloadOptions.headers
3157
- },
3158
- onBefore: (visit) => {
3159
- side === "next" ? options.onBeforeNextRequest() : options.onBeforePreviousRequest();
3160
- reloadOptions.onBefore?.(visit);
3161
- },
3162
- onBeforeUpdate: (page3) => {
3163
- options.onBeforeUpdate();
3164
- reloadOptions.onBeforeUpdate?.(page3);
3165
- },
3166
- onSuccess: (page3) => {
3167
- syncStateOnSuccess(side);
3168
- reloadOptions.onSuccess?.(page3);
3169
- },
3170
- onFinish: (visit) => {
3171
- state.loading = false;
3172
- side === "next" ? options.onCompleteNextRequest(state.lastLoadedPage) : options.onCompletePreviousRequest(state.lastLoadedPage);
3173
- reloadOptions.onFinish?.(visit);
3174
- }
3175
- });
3176
- };
3177
- const getLastLoadedPage = () => state.lastLoadedPage;
3178
- const hasPrevious = () => !!state.previousPage;
3179
- const hasNext = () => !!state.nextPage;
3180
- const fetchPrevious = (reloadOptions) => fetchPage("previous", reloadOptions);
3181
- const fetchNext = (reloadOptions) => fetchPage("next", reloadOptions);
3182
- return {
3183
- getLastLoadedPage,
3184
- getPageName,
3185
- getRequestCount,
3186
- hasPrevious,
3187
- hasNext,
3188
- fetchNext,
3189
- fetchPrevious,
3190
- removeEventListener
3191
- };
3192
- };
3193
-
3194
- // src/intersectionObservers.ts
3195
- var useIntersectionObservers = () => {
3196
- const intersectionObservers = [];
3197
- const newIntersectionObserver = (callback, options = {}) => {
3198
- const observer = new IntersectionObserver((entries) => {
3199
- for (const entry of entries) {
3200
- if (entry.isIntersecting) {
3201
- callback(entry);
3202
- }
3203
- }
3204
- }, options);
3205
- intersectionObservers.push(observer);
3206
- return observer;
3207
- };
3208
- const flushAll = () => {
3209
- intersectionObservers.forEach((observer) => observer.disconnect());
3210
- intersectionObservers.length = 0;
3211
- };
3212
- return {
3213
- new: newIntersectionObserver,
3214
- flushAll
3215
- };
3216
- };
3217
-
3218
- // src/infiniteScroll/elements.ts
3219
- var INFINITE_SCROLL_PAGE_KEY = "infiniteScrollPage";
3220
- var INFINITE_SCROLL_IGNORE_KEY = "infiniteScrollIgnore";
3221
- var getPageFromElement = (element) => element.dataset[INFINITE_SCROLL_PAGE_KEY];
3222
- var useInfiniteScrollElementManager = (options) => {
3223
- const intersectionObservers = useIntersectionObservers();
3224
- let itemsObserver;
3225
- let startElementObserver;
3226
- let endElementObserver;
3227
- let itemsMutationObserver;
3228
- let triggersEnabled = false;
3229
- const setupObservers = () => {
3230
- itemsMutationObserver = new MutationObserver((mutations) => {
3231
- mutations.forEach((mutation) => {
3232
- mutation.addedNodes.forEach((node) => {
3233
- if (node.nodeType !== Node.ELEMENT_NODE) {
3234
- return;
3235
- }
3236
- addedElements.add(node);
3237
- });
3238
- });
3239
- rememberElementsDebounced();
3240
- });
3241
- itemsMutationObserver.observe(options.getItemsElement(), { childList: true });
3242
- itemsObserver = intersectionObservers.new(
3243
- (entry) => options.onItemIntersected(entry.target)
3244
- );
3245
- const observerOptions = {
3246
- root: options.getScrollableParent(),
3247
- rootMargin: `${Math.max(1, options.getTriggerMargin())}px`
3248
- };
3249
- startElementObserver = intersectionObservers.new(options.onPreviousTriggered, observerOptions);
3250
- endElementObserver = intersectionObservers.new(options.onNextTriggered, observerOptions);
3251
- };
3252
- const enableTriggers = () => {
3253
- if (triggersEnabled) {
3254
- disableTriggers();
3255
- }
3256
- const startElement = options.getStartElement();
3257
- const endElement = options.getEndElement();
3258
- if (startElement && options.shouldFetchPrevious()) {
3259
- startElementObserver.observe(startElement);
3260
- }
3261
- if (endElement && options.shouldFetchNext()) {
3262
- endElementObserver.observe(endElement);
3263
- }
3264
- triggersEnabled = true;
3265
- };
3266
- const disableTriggers = () => {
3267
- if (!triggersEnabled) {
3268
- return;
3269
- }
3270
- startElementObserver.disconnect();
3271
- endElementObserver.disconnect();
3272
- triggersEnabled = false;
3273
- };
3274
- const refreshTriggers = () => {
3275
- if (triggersEnabled) {
3276
- enableTriggers();
3277
- }
3278
- };
3279
- const flushAll = () => {
3280
- disableTriggers();
3281
- intersectionObservers.flushAll();
3282
- itemsMutationObserver?.disconnect();
3283
- };
3284
- const addedElements = /* @__PURE__ */ new Set();
3285
- const elementIsUntagged = (element) => !(INFINITE_SCROLL_PAGE_KEY in element.dataset) && !(INFINITE_SCROLL_IGNORE_KEY in element.dataset);
3286
- const processManuallyAddedElements = () => {
3287
- Array.from(addedElements).forEach((element) => {
3288
- if (elementIsUntagged(element)) {
3289
- element.dataset[INFINITE_SCROLL_IGNORE_KEY] = "true";
3290
- }
3291
- itemsObserver.observe(element);
3292
- });
3293
- addedElements.clear();
3294
- };
3295
- const findUntaggedElements = (containerElement) => {
3296
- return Array.from(
3297
- containerElement.querySelectorAll(
3298
- `:scope > *:not([data-infinite-scroll-page]):not([data-infinite-scroll-ignore])`
3299
- )
3300
- );
3301
- };
3302
- let hasRestoredElements = false;
3303
- const processServerLoadedElements = (loadedPage) => {
3304
- if (!hasRestoredElements) {
3305
- hasRestoredElements = true;
3306
- if (restoreElements()) {
3307
- return;
3308
- }
3309
- }
3310
- findUntaggedElements(options.getItemsElement()).forEach((element) => {
3311
- if (elementIsUntagged(element)) {
3312
- element.dataset[INFINITE_SCROLL_PAGE_KEY] = loadedPage?.toString() || "1";
3313
- }
3314
- itemsObserver.observe(element);
3315
- });
3316
- rememberElements();
3317
- };
3318
- const getElementsRememberKey = () => `inertia:infinite-scroll-elements:${options.getPropName()}`;
3319
- const rememberElements = () => {
3320
- const pageElementRange = {};
3321
- const childNodes = options.getItemsElement().childNodes;
3322
- for (let index = 0; index < childNodes.length; index++) {
3323
- const node = childNodes[index];
3324
- if (node.nodeType !== Node.ELEMENT_NODE) {
3325
- continue;
3326
- }
3327
- const page2 = getPageFromElement(node);
3328
- if (typeof page2 === "undefined") {
3329
- continue;
3330
- }
3331
- if (!(page2 in pageElementRange)) {
3332
- pageElementRange[page2] = { from: index, to: index };
3333
- } else {
3334
- pageElementRange[page2].to = index;
3335
- }
3336
- }
3337
- router.remember(pageElementRange, getElementsRememberKey());
3338
- };
3339
- const rememberElementsDebounced = debounce(rememberElements, 250);
3340
- const restoreElements = () => {
3341
- const pageElementRange = router.restore(getElementsRememberKey());
3342
- if (!pageElementRange || typeof pageElementRange !== "object") {
3343
- return false;
3344
- }
3345
- const childNodes = options.getItemsElement().childNodes;
3346
- for (let index = 0; index < childNodes.length; index++) {
3347
- const node = childNodes[index];
3348
- if (node.nodeType !== Node.ELEMENT_NODE) {
3349
- continue;
3350
- }
3351
- const element = node;
3352
- let elementPage;
3353
- for (const [page2, range] of Object.entries(pageElementRange)) {
3354
- if (index >= range.from && index <= range.to) {
3355
- elementPage = page2;
3356
- break;
3357
- }
3358
- }
3359
- if (elementPage) {
3360
- element.dataset[INFINITE_SCROLL_PAGE_KEY] = elementPage;
3361
- } else if (!elementIsUntagged(element)) {
3362
- continue;
3363
- } else {
3364
- element.dataset[INFINITE_SCROLL_IGNORE_KEY] = "true";
3365
- }
3366
- itemsObserver.observe(element);
3367
- }
3368
- return true;
3369
- };
3370
- return {
3371
- setupObservers,
3372
- enableTriggers,
3373
- disableTriggers,
3374
- refreshTriggers,
3375
- flushAll,
3376
- processManuallyAddedElements,
3377
- processServerLoadedElements
3378
- };
3379
- };
3380
-
3381
- // src/infiniteScroll/queryString.ts
3382
- var queue3 = new Queue();
3383
- var initialUrl;
3384
- var payloadUrl;
3385
- var initialUrlWasAbsolute = null;
3386
- var useInfiniteScrollQueryString = (options) => {
3387
- let enabled = true;
3388
- const queuePageUpdate = (page2) => {
3389
- queue3.add(() => {
3390
- return new Promise((resolve) => {
3391
- if (!enabled) {
3392
- initialUrl = payloadUrl = null;
3393
- return resolve();
3394
- }
3395
- if (!initialUrl || !payloadUrl) {
3396
- const currentPageUrl = page.get().url;
3397
- initialUrl = hrefToUrl(currentPageUrl);
3398
- payloadUrl = hrefToUrl(currentPageUrl);
3399
- initialUrlWasAbsolute = urlHasProtocol(currentPageUrl);
3400
- }
3401
- const pageName = options.getPageName();
3402
- const searchParams = payloadUrl.searchParams;
3403
- if (page2 === "1") {
3404
- searchParams.delete(pageName);
3405
- } else {
3406
- searchParams.set(pageName, page2);
3407
- }
3408
- setTimeout(() => resolve());
3409
- });
3410
- }).finally(() => {
3411
- if (enabled && initialUrl && payloadUrl && initialUrl.href !== payloadUrl.href && initialUrlWasAbsolute !== null) {
3412
- router.replace({
3413
- url: urlToString(payloadUrl, initialUrlWasAbsolute),
3414
- preserveScroll: true,
3415
- preserveState: true
3416
- });
3417
- }
3418
- initialUrl = payloadUrl = initialUrlWasAbsolute = null;
3419
- });
3420
- };
3421
- const onItemIntersected = debounce((itemElement) => {
3422
- const itemsElement = options.getItemsElement();
3423
- if (!enabled || options.shouldPreserveUrl() || !itemElement || !itemsElement) {
3424
- return;
3425
- }
3426
- const pageMap = /* @__PURE__ */ new Map();
3427
- const elements = [...itemsElement.children];
3428
- getElementsInViewportFromCollection(elements, itemElement).forEach((element) => {
3429
- const page2 = getPageFromElement(element) ?? "1";
3430
- if (pageMap.has(page2)) {
3431
- pageMap.set(page2, pageMap.get(page2) + 1);
3432
- } else {
3433
- pageMap.set(page2, 1);
3434
- }
3435
- });
3436
- const sortedPages = Array.from(pageMap.entries()).sort((a, b) => b[1] - a[1]);
3437
- const mostVisiblePage = sortedPages[0]?.[0];
3438
- if (mostVisiblePage !== void 0) {
3439
- queuePageUpdate(mostVisiblePage);
3440
- }
3441
- }, 250);
3442
- return {
3443
- onItemIntersected,
3444
- cancel: () => enabled = false
3445
- };
3446
- };
3447
-
3448
- // src/infiniteScroll/scrollPreservation.ts
3449
- var useInfiniteScrollPreservation = (options) => {
3450
- const createCallbacks = () => {
3451
- let currentScrollTop;
3452
- let referenceElement = null;
3453
- let referenceElementTop = 0;
3454
- const captureScrollPosition = () => {
3455
- const scrollableContainer = options.getScrollableParent();
3456
- const itemsElement = options.getItemsElement();
3457
- currentScrollTop = scrollableContainer?.scrollTop || window.scrollY;
3458
- const visibleElements = getElementsInViewportFromCollection([...itemsElement.children]);
3459
- if (visibleElements.length > 0) {
3460
- referenceElement = visibleElements[0];
3461
- const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 };
3462
- const containerTop = scrollableContainer ? containerRect.top : 0;
3463
- const rect = referenceElement.getBoundingClientRect();
3464
- referenceElementTop = rect.top - containerTop;
3465
- }
3466
- };
3467
- const restoreScrollPosition = () => {
3468
- if (!referenceElement) {
3469
- return;
3470
- }
3471
- let attempts = 0;
3472
- let restored = false;
3473
- const restore = () => {
3474
- attempts++;
3475
- if (restored || attempts > 10) {
3476
- return false;
3477
- }
3478
- const scrollableContainer = options.getScrollableParent();
3479
- const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 };
3480
- const containerTop = scrollableContainer ? containerRect.top : 0;
3481
- const newRect = referenceElement.getBoundingClientRect();
3482
- const newElementTop = newRect.top - containerTop;
3483
- const adjustment = newElementTop - referenceElementTop;
3484
- if (adjustment === 0) {
3485
- window.requestAnimationFrame(restore);
3486
- return;
3487
- }
3488
- if (scrollableContainer) {
3489
- scrollableContainer.scrollTo({ top: currentScrollTop + adjustment });
3490
- } else {
3491
- window.scrollTo(0, window.scrollY + adjustment);
3492
- }
3493
- restored = true;
3494
- };
3495
- window.requestAnimationFrame(restore);
3496
- };
3497
- return {
3498
- captureScrollPosition,
3499
- restoreScrollPosition
3500
- };
3501
- };
3502
- return {
3503
- createCallbacks
3504
- };
3505
- };
3506
-
3507
- // src/infiniteScroll.ts
3508
- function useInfiniteScroll(options) {
3509
- const queryStringManager = useInfiniteScrollQueryString({ ...options, getPageName: () => dataManager.getPageName() });
3510
- const scrollPreservation = useInfiniteScrollPreservation(options);
3511
- const elementManager = useInfiniteScrollElementManager({
3512
- ...options,
3513
- // As items enter viewport, update URL to reflect the most visible page
3514
- onItemIntersected: queryStringManager.onItemIntersected,
3515
- onPreviousTriggered: () => dataManager.fetchPrevious(),
3516
- onNextTriggered: () => dataManager.fetchNext()
3517
- });
3518
- const dataManager = useInfiniteScrollData({
3519
- ...options,
3520
- // Before updating page data, tag any manually added DOM elements
3521
- // so they don't get confused with server-loaded content
3522
- onBeforeUpdate: elementManager.processManuallyAddedElements,
3523
- // After successful request, tag new server content
3524
- onCompletePreviousRequest: (loadedPage) => {
3525
- options.onCompletePreviousRequest();
3526
- requestAnimationFrame(() => elementManager.processServerLoadedElements(loadedPage), 2);
3527
- },
3528
- onCompleteNextRequest: (loadedPage) => {
3529
- options.onCompleteNextRequest();
3530
- requestAnimationFrame(() => elementManager.processServerLoadedElements(loadedPage), 2);
3531
- },
3532
- onReset: options.onDataReset
3533
- });
3534
- const addScrollPreservationCallbacks = (reloadOptions) => {
3535
- const { captureScrollPosition, restoreScrollPosition } = scrollPreservation.createCallbacks();
3536
- const originalOnBeforeUpdate = reloadOptions.onBeforeUpdate || (() => {
3537
- });
3538
- const originalOnSuccess = reloadOptions.onSuccess || (() => {
3539
- });
3540
- reloadOptions.onBeforeUpdate = (page2) => {
3541
- originalOnBeforeUpdate(page2);
3542
- captureScrollPosition();
3543
- };
3544
- reloadOptions.onSuccess = (page2) => {
3545
- originalOnSuccess(page2);
3546
- restoreScrollPosition();
3547
- };
3548
- return reloadOptions;
3549
- };
3550
- const originalFetchNext = dataManager.fetchNext;
3551
- dataManager.fetchNext = (reloadOptions = {}) => {
3552
- if (options.inReverseMode()) {
3553
- reloadOptions = addScrollPreservationCallbacks(reloadOptions);
3554
- }
3555
- originalFetchNext(reloadOptions);
3556
- };
3557
- const originalFetchPrevious = dataManager.fetchPrevious;
3558
- dataManager.fetchPrevious = (reloadOptions = {}) => {
3559
- if (!options.inReverseMode()) {
3560
- reloadOptions = addScrollPreservationCallbacks(reloadOptions);
3561
- }
3562
- originalFetchPrevious(reloadOptions);
3563
- };
3564
- const removeEventListener = router.on("success", () => requestAnimationFrame(elementManager.refreshTriggers, 2));
3565
- return {
3566
- dataManager,
3567
- elementManager,
3568
- flush: () => {
3569
- removeEventListener();
3570
- dataManager.removeEventListener();
3571
- elementManager.flushAll();
3572
- queryStringManager.cancel();
3573
- }
3574
- };
3575
- }
3576
-
3577
- // src/navigationEvents.ts
3578
- function isContentEditableOrPrevented(event) {
3579
- return event.target instanceof HTMLElement && event.target.isContentEditable || event.defaultPrevented;
3580
- }
3581
- function shouldIntercept(event) {
3582
- const isLink = event.currentTarget.tagName.toLowerCase() === "a";
3583
- return !(isContentEditableOrPrevented(event) || isLink && event.altKey || isLink && event.ctrlKey || isLink && event.metaKey || isLink && event.shiftKey || isLink && "button" in event && event.button !== 0);
3584
- }
3585
- function shouldNavigate(event) {
3586
- const isButton = event.currentTarget.tagName.toLowerCase() === "button";
3587
- return !isContentEditableOrPrevented(event) && (event.key === "Enter" || isButton && event.key === " ");
3588
- }
3589
-
3590
- // src/progress-component.ts
3591
- var baseComponentSelector = "nprogress";
3592
- var progress2;
3593
- var settings = {
3594
- minimum: 0.08,
3595
- easing: "linear",
3596
- positionUsing: "translate3d",
3597
- speed: 200,
3598
- trickle: true,
3599
- trickleSpeed: 200,
3600
- showSpinner: true,
3601
- barSelector: '[role="bar"]',
3602
- spinnerSelector: '[role="spinner"]',
3603
- parent: "body",
3604
- color: "#29d",
3605
- includeCSS: true,
3606
- template: [
3607
- '<div class="bar" role="bar">',
3608
- '<div class="peg"></div>',
3609
- "</div>",
3610
- '<div class="spinner" role="spinner">',
3611
- '<div class="spinner-icon"></div>',
3612
- "</div>"
3613
- ].join("")
3614
- };
3615
- var status = null;
3616
- var configure = (options) => {
3617
- Object.assign(settings, options);
3618
- if (settings.includeCSS) {
3619
- injectCSS(settings.color);
3620
- }
3621
- progress2 = document.createElement("div");
3622
- progress2.id = baseComponentSelector;
3623
- progress2.innerHTML = settings.template;
3624
- };
3625
- var set5 = (n) => {
3626
- const started = isStarted();
3627
- n = clamp(n, settings.minimum, 1);
3628
- status = n === 1 ? null : n;
3629
- const progress3 = render(!started);
3630
- const bar = progress3.querySelector(settings.barSelector);
3631
- const speed = settings.speed;
3632
- const ease = settings.easing;
3633
- progress3.offsetWidth;
3634
- queue4((next) => {
3635
- const barStyles = (() => {
3636
- if (settings.positionUsing === "translate3d") {
3637
- return {
3638
- transition: `all ${speed}ms ${ease}`,
3639
- transform: `translate3d(${toBarPercentage(n)}%,0,0)`
3640
- };
3641
- }
3642
- if (settings.positionUsing === "translate") {
3643
- return {
3644
- transition: `all ${speed}ms ${ease}`,
3645
- transform: `translate(${toBarPercentage(n)}%,0)`
3646
- };
3647
- }
3648
- return { marginLeft: `${toBarPercentage(n)}%` };
3649
- })();
3650
- for (const key in barStyles) {
3651
- bar.style[key] = barStyles[key];
3652
- }
3653
- if (n !== 1) {
3654
- return setTimeout(next, speed);
3655
- }
3656
- progress3.style.transition = "none";
3657
- progress3.style.opacity = "1";
3658
- progress3.offsetWidth;
3659
- setTimeout(() => {
3660
- progress3.style.transition = `all ${speed}ms linear`;
3661
- progress3.style.opacity = "0";
3662
- setTimeout(() => {
3663
- remove();
3664
- progress3.style.transition = "";
3665
- progress3.style.opacity = "";
3666
- next();
3667
- }, speed);
3668
- }, speed);
3669
- });
3670
- };
3671
- var isStarted = () => typeof status === "number";
3672
- var start = () => {
3673
- if (!status) {
3674
- set5(0);
3675
- }
3676
- const work = function() {
3677
- setTimeout(function() {
3678
- if (!status) {
3679
- return;
3680
- }
3681
- increaseByRandom();
3682
- work();
3683
- }, settings.trickleSpeed);
3684
- };
3685
- if (settings.trickle) {
3686
- work();
3687
- }
3688
- };
3689
- var done = (force) => {
3690
- if (!force && !status) {
3691
- return;
3692
- }
3693
- increaseByRandom(0.3 + 0.5 * Math.random());
3694
- set5(1);
3695
- };
3696
- var increaseByRandom = (amount) => {
3697
- const n = status;
3698
- if (n === null) {
3699
- return start();
3700
- }
3701
- if (n > 1) {
3702
- return;
3703
- }
3704
- amount = typeof amount === "number" ? amount : (() => {
3705
- const ranges = {
3706
- 0.1: [0, 0.2],
3707
- 0.04: [0.2, 0.5],
3708
- 0.02: [0.5, 0.8],
3709
- 5e-3: [0.8, 0.99]
3710
- };
3711
- for (const r in ranges) {
3712
- if (n >= ranges[r][0] && n < ranges[r][1]) {
3713
- return parseFloat(r);
3714
- }
3715
- }
3716
- return 0;
3717
- })();
3718
- return set5(clamp(n + amount, 0, 0.994));
3719
- };
3720
- var render = (fromStart) => {
3721
- if (isRendered()) {
3722
- return document.getElementById(baseComponentSelector);
3723
- }
3724
- document.documentElement.classList.add(`${baseComponentSelector}-busy`);
3725
- const bar = progress2.querySelector(settings.barSelector);
3726
- const perc = fromStart ? "-100" : toBarPercentage(status || 0);
3727
- const parent = getParent();
3728
- bar.style.transition = "all 0 linear";
3729
- bar.style.transform = `translate3d(${perc}%,0,0)`;
3730
- if (!settings.showSpinner) {
3731
- progress2.querySelector(settings.spinnerSelector)?.remove();
3732
- }
3733
- if (parent !== document.body) {
3734
- parent.classList.add(`${baseComponentSelector}-custom-parent`);
3735
- }
3736
- parent.appendChild(progress2);
3737
- return progress2;
3738
- };
3739
- var getParent = () => {
3740
- return isDOM(settings.parent) ? settings.parent : document.querySelector(settings.parent);
3741
- };
3742
- var remove = () => {
3743
- document.documentElement.classList.remove(`${baseComponentSelector}-busy`);
3744
- getParent().classList.remove(`${baseComponentSelector}-custom-parent`);
3745
- progress2?.remove();
3746
- };
3747
- var isRendered = () => {
3748
- return document.getElementById(baseComponentSelector) !== null;
3749
- };
3750
- var isDOM = (obj) => {
3751
- if (typeof HTMLElement === "object") {
3752
- return obj instanceof HTMLElement;
3753
- }
3754
- return obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string";
3755
- };
3756
- function clamp(n, min, max) {
3757
- if (n < min) {
3758
- return min;
3759
- }
3760
- if (n > max) {
3761
- return max;
3762
- }
3763
- return n;
3764
- }
3765
- var toBarPercentage = (n) => (-1 + n) * 100;
3766
- var queue4 = /* @__PURE__ */ (() => {
3767
- const pending = [];
3768
- const next = () => {
3769
- const fn = pending.shift();
3770
- if (fn) {
3771
- fn(next);
3772
- }
3773
- };
3774
- return (fn) => {
3775
- pending.push(fn);
3776
- if (pending.length === 1) {
3777
- next();
3778
- }
3779
- };
3780
- })();
3781
- var injectCSS = (color) => {
3782
- const element = document.createElement("style");
3783
- element.textContent = `
3784
- #${baseComponentSelector} {
3785
- pointer-events: none;
3786
- }
3787
-
3788
- #${baseComponentSelector} .bar {
3789
- background: ${color};
3790
-
3791
- position: fixed;
3792
- z-index: 1031;
3793
- top: 0;
3794
- left: 0;
3795
-
3796
- width: 100%;
3797
- height: 2px;
3798
- }
3799
-
3800
- #${baseComponentSelector} .peg {
3801
- display: block;
3802
- position: absolute;
3803
- right: 0px;
3804
- width: 100px;
3805
- height: 100%;
3806
- box-shadow: 0 0 10px ${color}, 0 0 5px ${color};
3807
- opacity: 1.0;
3808
-
3809
- transform: rotate(3deg) translate(0px, -4px);
3810
- }
3811
-
3812
- #${baseComponentSelector} .spinner {
3813
- display: block;
3814
- position: fixed;
3815
- z-index: 1031;
3816
- top: 15px;
3817
- right: 15px;
3818
- }
3819
-
3820
- #${baseComponentSelector} .spinner-icon {
3821
- width: 18px;
3822
- height: 18px;
3823
- box-sizing: border-box;
3824
-
3825
- border: solid 2px transparent;
3826
- border-top-color: ${color};
3827
- border-left-color: ${color};
3828
- border-radius: 50%;
3829
-
3830
- animation: ${baseComponentSelector}-spinner 400ms linear infinite;
3831
- }
3832
-
3833
- .${baseComponentSelector}-custom-parent {
3834
- overflow: hidden;
3835
- position: relative;
3836
- }
3837
-
3838
- .${baseComponentSelector}-custom-parent #${baseComponentSelector} .spinner,
3839
- .${baseComponentSelector}-custom-parent #${baseComponentSelector} .bar {
3840
- position: absolute;
3841
- }
3842
-
3843
- @keyframes ${baseComponentSelector}-spinner {
3844
- 0% { transform: rotate(0deg); }
3845
- 100% { transform: rotate(360deg); }
3846
- }
3847
- `;
3848
- document.head.appendChild(element);
3849
- };
3850
- var show = () => {
3851
- if (progress2) {
3852
- progress2.style.display = "";
3853
- }
3854
- };
3855
- var hide = () => {
3856
- if (progress2) {
3857
- progress2.style.display = "none";
3858
- }
3859
- };
3860
- var progress_component_default = {
3861
- configure,
3862
- isStarted,
3863
- done,
3864
- set: set5,
3865
- remove,
3866
- start,
3867
- status,
3868
- show,
3869
- hide
3870
- };
3871
-
3872
- // src/progress.ts
3873
- var Progress = class {
3874
- constructor() {
3875
- this.hideCount = 0;
3876
- }
3877
- start() {
3878
- progress_component_default.start();
3879
- }
3880
- reveal(force = false) {
3881
- this.hideCount = Math.max(0, this.hideCount - 1);
3882
- if (force || this.hideCount === 0) {
3883
- progress_component_default.show();
3884
- }
3885
- }
3886
- hide() {
3887
- this.hideCount++;
3888
- progress_component_default.hide();
3889
- }
3890
- set(status2) {
3891
- progress_component_default.set(Math.max(0, Math.min(1, status2)));
3892
- }
3893
- finish() {
3894
- progress_component_default.done();
3895
- }
3896
- reset() {
3897
- progress_component_default.set(0);
3898
- }
3899
- remove() {
3900
- progress_component_default.done();
3901
- progress_component_default.remove();
3902
- }
3903
- isStarted() {
3904
- return progress_component_default.isStarted();
3905
- }
3906
- getStatus() {
3907
- return progress_component_default.status;
3908
- }
3909
- };
3910
- var progress = new Progress();
3911
- var reveal = progress.reveal;
3912
- var hide2 = progress.hide;
3913
- function addEventListeners(delay) {
3914
- document.addEventListener("inertia:start", (e) => handleStartEvent(e, delay));
3915
- document.addEventListener("inertia:progress", handleProgressEvent);
3916
- }
3917
- function handleStartEvent(event, delay) {
3918
- if (!event.detail.visit.showProgress) {
3919
- progress.hide();
3920
- }
3921
- const timeout = setTimeout(() => progress.start(), delay);
3922
- document.addEventListener("inertia:finish", (e) => finish(e, timeout), { once: true });
3923
- }
3924
- function handleProgressEvent(event) {
3925
- if (progress.isStarted() && event.detail.progress?.percentage) {
3926
- progress.set(Math.max(progress.getStatus(), event.detail.progress.percentage / 100 * 0.9));
3927
- }
3928
- }
3929
- function finish(event, timeout) {
3930
- clearTimeout(timeout);
3931
- if (!progress.isStarted()) {
3932
- return;
3933
- }
3934
- if (event.detail.visit.completed) {
3935
- progress.finish();
3936
- } else if (event.detail.visit.interrupted) {
3937
- progress.reset();
3938
- } else if (event.detail.visit.cancelled) {
3939
- progress.remove();
3940
- }
3941
- }
3942
- function setupProgress({
3943
- delay = 250,
3944
- color = "#29d",
3945
- includeCSS = true,
3946
- showSpinner = false
3947
- } = {}) {
3948
- addEventListeners(delay);
3949
- progress_component_default.configure({ showSpinner, includeCSS, color });
3950
- }
3951
-
3952
- // src/resetFormFields.ts
3953
- var FormComponentResetSymbol = /* @__PURE__ */ Symbol("FormComponentReset");
3954
- function isFormElement(element) {
3955
- return element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement;
3956
- }
3957
- function resetInputElement(input, defaultValues) {
3958
- const oldValue = input.value;
3959
- const oldChecked = input.checked;
3960
- switch (input.type.toLowerCase()) {
3961
- case "checkbox":
3962
- input.checked = defaultValues.includes(input.value);
3963
- break;
3964
- case "radio":
3965
- input.checked = defaultValues[0] === input.value;
3966
- break;
3967
- case "file":
3968
- input.value = "";
3969
- break;
3970
- case "button":
3971
- case "submit":
3972
- case "reset":
3973
- case "image":
3974
- break;
3975
- default:
3976
- input.value = defaultValues[0] !== null && defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
3977
- }
3978
- return input.value !== oldValue || input.checked !== oldChecked;
3979
- }
3980
- function resetSelectElement(select, defaultValues) {
3981
- const oldValue = select.value;
3982
- const oldSelectedOptions = Array.from(select.selectedOptions).map((opt) => opt.value);
3983
- if (select.multiple) {
3984
- const defaultStrings = defaultValues.map((value) => String(value));
3985
- Array.from(select.options).forEach((option) => {
3986
- option.selected = defaultStrings.includes(option.value);
3987
- });
3988
- } else {
3989
- select.value = defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
3990
- }
3991
- const newSelectedOptions = Array.from(select.selectedOptions).map((opt) => opt.value);
3992
- const hasChanged = select.multiple ? JSON.stringify(oldSelectedOptions.sort()) !== JSON.stringify(newSelectedOptions.sort()) : select.value !== oldValue;
3993
- return hasChanged;
3994
- }
3995
- function resetFormElement(element, defaultValues) {
3996
- if (element.disabled) {
3997
- if (element instanceof HTMLInputElement) {
3998
- const oldValue = element.value;
3999
- const oldChecked = element.checked;
4000
- switch (element.type.toLowerCase()) {
4001
- case "checkbox":
4002
- case "radio":
4003
- element.checked = element.defaultChecked;
4004
- return element.checked !== oldChecked;
4005
- case "file":
4006
- element.value = "";
4007
- return oldValue !== "";
4008
- case "button":
4009
- case "submit":
4010
- case "reset":
4011
- case "image":
4012
- return false;
4013
- default:
4014
- element.value = element.defaultValue;
4015
- return element.value !== oldValue;
4016
- }
4017
- } else if (element instanceof HTMLSelectElement) {
4018
- const oldSelectedOptions = Array.from(element.selectedOptions).map((opt) => opt.value);
4019
- Array.from(element.options).forEach((option) => {
4020
- option.selected = option.defaultSelected;
4021
- });
4022
- const newSelectedOptions = Array.from(element.selectedOptions).map((opt) => opt.value);
4023
- return JSON.stringify(oldSelectedOptions.sort()) !== JSON.stringify(newSelectedOptions.sort());
4024
- } else if (element instanceof HTMLTextAreaElement) {
4025
- const oldValue = element.value;
4026
- element.value = element.defaultValue;
4027
- return element.value !== oldValue;
4028
- }
4029
- return false;
4030
- }
4031
- if (element instanceof HTMLInputElement) {
4032
- return resetInputElement(element, defaultValues);
4033
- } else if (element instanceof HTMLSelectElement) {
4034
- return resetSelectElement(element, defaultValues);
4035
- } else if (element instanceof HTMLTextAreaElement) {
4036
- const oldValue = element.value;
4037
- element.value = defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
4038
- return element.value !== oldValue;
4039
- }
4040
- return false;
4041
- }
4042
- function resetFieldElements(elements, defaultValues) {
4043
- let hasChanged = false;
4044
- if (elements instanceof RadioNodeList || elements instanceof HTMLCollection) {
4045
- Array.from(elements).forEach((node, index) => {
4046
- if (node instanceof Element && isFormElement(node)) {
4047
- if (node instanceof HTMLInputElement && ["checkbox", "radio"].includes(node.type.toLowerCase())) {
4048
- if (resetFormElement(node, defaultValues)) {
4049
- hasChanged = true;
4050
- }
4051
- } else {
4052
- const indexedDefaultValues = defaultValues[index] !== void 0 ? [defaultValues[index]] : [defaultValues[0] ?? null].filter(Boolean);
4053
- if (resetFormElement(node, indexedDefaultValues)) {
4054
- hasChanged = true;
4055
- }
4056
- }
4057
- }
4058
- });
4059
- } else if (isFormElement(elements)) {
4060
- hasChanged = resetFormElement(elements, defaultValues);
4061
- }
4062
- return hasChanged;
4063
- }
4064
- function resetFormFields(formElement, defaults, fieldNames) {
4065
- if (!formElement) {
4066
- return;
4067
- }
4068
- const resetEntireForm = !fieldNames || fieldNames.length === 0;
4069
- if (resetEntireForm) {
4070
- const formData = new FormData(formElement);
4071
- const formElementNames = Array.from(formElement.elements).map((el) => isFormElement(el) ? el.name : "").filter(Boolean);
4072
- fieldNames = [.../* @__PURE__ */ new Set([...defaults.keys(), ...formData.keys(), ...formElementNames])];
4073
- }
4074
- let hasChanged = false;
4075
- fieldNames.forEach((fieldName) => {
4076
- const elements = formElement.elements.namedItem(fieldName);
4077
- if (elements) {
4078
- if (resetFieldElements(elements, defaults.getAll(fieldName))) {
4079
- hasChanged = true;
4080
- }
4081
- }
4082
- });
4083
- if (hasChanged && resetEntireForm) {
4084
- formElement.dispatchEvent(
4085
- new CustomEvent("reset", { bubbles: true, cancelable: true, detail: { [FormComponentResetSymbol]: true } })
4086
- );
4087
- }
4088
- }
4089
-
4090
- // src/index.ts
4091
- var router = new Router();
4092
- export {
4093
- FormComponentResetSymbol,
4094
- UseFormUtils,
4095
- config,
4096
- createHeadManager,
4097
- formDataToObject,
4098
- getInitialPageFromDOM,
4099
- getScrollableParent,
4100
- hide2 as hideProgress,
4101
- hrefToUrl,
4102
- isUrlMethodPair,
4103
- mergeDataIntoQueryString,
4104
- objectToFormData,
4105
- progress,
4106
- resetFormFields,
4107
- reveal as revealProgress,
4108
- router,
4109
- setupProgress,
4110
- shouldIntercept,
4111
- shouldNavigate,
4112
- urlHasProtocol,
4113
- urlToString,
4114
- urlWithoutHash,
4115
- useInfiniteScroll
4116
- };
4117
- /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
4118
- * @license MIT */
4119
- //# sourceMappingURL=index.esm.js.map