@inertiaui/modal-react 2.0.2 → 3.0.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.
@@ -1,6 +1,6 @@
1
1
  (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("axios"), require("@inertiaui/vanilla"), require("@inertiajs/react"), require("@inertiajs/core"), require("react-dom")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime", "axios", "@inertiaui/vanilla", "@inertiajs/react", "@inertiajs/core", "react-dom"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.InertiaUIModal = {}, global.React, global.ReactJSXRuntime, global.axios, global.InertiaUIVanilla, global.InertiaReact, global.InertiaCore, global.ReactDOM));
3
- })(this, (function(exports2, React, jsxRuntime, Axios, vanilla, react, core, reactDom) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("@inertiaui/vanilla"), require("@inertiajs/react"), require("@inertiajs/core"), require("react-dom")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime", "@inertiaui/vanilla", "@inertiajs/react", "@inertiajs/core", "react-dom"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.InertiaUIModal = {}, global.React, global.ReactJSXRuntime, global.InertiaUIVanilla, global.InertiaReact, global.InertiaCore, global.ReactDOM));
3
+ })(this, (function(exports2, React, jsxRuntime, vanilla, react, core, reactDom) {
4
4
  "use strict";
5
5
  function _interopNamespaceDefault(e) {
6
6
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -90,56 +90,81 @@
90
90
  const putConfig = (key, value) => configInstance.put(key, value);
91
91
  const getConfig = (key) => configInstance.get(key);
92
92
  const getConfigByType = (isSlideover, key) => configInstance.get(isSlideover ? `slideover.${key}` : `modal.${key}`);
93
+ function parseResponseData(data) {
94
+ return typeof data === "string" ? JSON.parse(data) : data;
95
+ }
93
96
  function generateId(prefix = "inertiaui_") {
94
97
  return vanilla.generateId(prefix);
95
98
  }
99
+ class ResponseCache {
100
+ constructor() {
101
+ this.cache = /* @__PURE__ */ new Map();
102
+ this.timers = /* @__PURE__ */ new Map();
103
+ this.inFlight = /* @__PURE__ */ new Map();
104
+ }
105
+ static key(method, url, data) {
106
+ return `${method}:${url}:${JSON.stringify(data)}`;
107
+ }
108
+ get(key) {
109
+ const cached = this.cache.get(key);
110
+ if (!cached) {
111
+ return null;
112
+ }
113
+ if (Date.now() > cached.expiresAt) {
114
+ this.delete(key);
115
+ return null;
116
+ }
117
+ return cached.response;
118
+ }
119
+ set(key, response, cacheFor) {
120
+ this.delete(key);
121
+ this.cache.set(key, {
122
+ response,
123
+ expiresAt: Date.now() + cacheFor
124
+ });
125
+ if (cacheFor > 0) {
126
+ this.timers.set(key, setTimeout(() => this.delete(key), cacheFor));
127
+ }
128
+ }
129
+ delete(key) {
130
+ this.cache.delete(key);
131
+ const timer = this.timers.get(key);
132
+ if (timer) {
133
+ clearTimeout(timer);
134
+ this.timers.delete(key);
135
+ }
136
+ }
137
+ getInFlight(key) {
138
+ return this.inFlight.get(key);
139
+ }
140
+ setInFlight(key, promise) {
141
+ this.inFlight.set(key, promise);
142
+ }
143
+ deleteInFlight(key) {
144
+ this.inFlight.delete(key);
145
+ }
146
+ }
96
147
  const ModalStackContext = React.createContext(null);
97
148
  ModalStackContext.displayName = "ModalStackContext";
98
- let pageVersion = null;
99
- let resolveComponent = null;
100
149
  let baseUrl = null;
150
+ let currentPageVersion = null;
101
151
  let closingToBaseUrlTarget = null;
102
- const prefetchCache = /* @__PURE__ */ new Map();
103
- const prefetchInFlight = /* @__PURE__ */ new Map();
104
- function getPrefetchCacheKey(url, method, data) {
105
- return `${method}:${url}:${JSON.stringify(data)}`;
106
- }
107
- function getCachedResponse(url, method, data) {
108
- const key = getPrefetchCacheKey(url, method, data);
109
- const cached = prefetchCache.get(key);
110
- if (!cached) {
111
- return null;
112
- }
113
- if (Date.now() > cached.expiresAt) {
114
- prefetchCache.delete(key);
115
- return null;
116
- }
117
- return cached.response;
118
- }
119
- function setCachedResponse(url, method, data, response, cacheFor) {
120
- const key = getPrefetchCacheKey(url, method, data);
121
- prefetchCache.set(key, {
122
- response,
123
- timestamp: Date.now(),
124
- expiresAt: Date.now() + cacheFor
125
- });
126
- }
152
+ const prefetchCache = new ResponseCache();
127
153
  function prefetch(href, options = {}) {
128
154
  if (href.startsWith("#")) {
129
155
  return Promise.resolve();
130
156
  }
131
- const method = (options.method ?? "get").toLowerCase();
157
+ const method = options.method ?? "get";
132
158
  const data = options.data ?? {};
133
159
  const headers = options.headers ?? {};
134
160
  const queryStringArrayFormat = options.queryStringArrayFormat ?? "brackets";
135
161
  const cacheFor = options.cacheFor ?? 3e4;
136
162
  const [url, mergedData] = core.mergeDataIntoQueryString(method, href || "", data, queryStringArrayFormat);
137
- const cached = getCachedResponse(url, method, mergedData);
138
- if (cached) {
163
+ const cacheKey = ResponseCache.key(method, url, mergedData);
164
+ if (prefetchCache.get(cacheKey)) {
139
165
  return Promise.resolve();
140
166
  }
141
- const cacheKey = getPrefetchCacheKey(url, method, mergedData);
142
- const inFlight = prefetchInFlight.get(cacheKey);
167
+ const inFlight = prefetchCache.getInFlight(cacheKey);
143
168
  if (inFlight) {
144
169
  return inFlight.then(() => {
145
170
  });
@@ -150,23 +175,23 @@
150
175
  Accept: "text/html, application/xhtml+xml",
151
176
  "X-Requested-With": "XMLHttpRequest",
152
177
  "X-Inertia": "true",
153
- "X-Inertia-Version": pageVersion ?? "",
178
+ "X-Inertia-Version": currentPageVersion ?? "",
154
179
  "X-InertiaUI-Modal": generateId(),
155
180
  "X-InertiaUI-Modal-Base-Url": baseUrl ?? ""
156
181
  };
157
- const request = Axios({
182
+ const request = react.http.getClient().request({
158
183
  url,
159
184
  method,
160
185
  data: mergedData,
161
186
  headers: requestHeaders
162
187
  }).then((response) => {
163
- setCachedResponse(url, method, mergedData, response, cacheFor);
188
+ prefetchCache.set(cacheKey, response, cacheFor);
164
189
  options.onPrefetched?.();
165
190
  return response;
166
191
  }).finally(() => {
167
- prefetchInFlight.delete(cacheKey);
192
+ prefetchCache.deleteInFlight(cacheKey);
168
193
  });
169
- prefetchInFlight.set(cacheKey, request);
194
+ prefetchCache.setInFlight(cacheKey, request);
170
195
  return request.then(() => {
171
196
  });
172
197
  }
@@ -254,7 +279,7 @@
254
279
  const savedBaseUrl = baseUrl;
255
280
  baseUrl = null;
256
281
  closingToBaseUrlTarget = savedBaseUrl;
257
- if (savedBaseUrl && typeof window !== "undefined") {
282
+ if (savedBaseUrl && typeof window !== "undefined" && !vanilla.sameUrlPath(savedBaseUrl, window.location.href)) {
258
283
  react.router.push({
259
284
  url: savedBaseUrl,
260
285
  preserveScroll: true,
@@ -308,14 +333,14 @@
308
333
  if (!this.response?.url) {
309
334
  return;
310
335
  }
311
- const method = (options.method ?? "get").toLowerCase();
336
+ const method = options.method ?? "get";
312
337
  const data = options.data ?? {};
313
338
  options.onStart?.();
314
- Axios({
339
+ react.http.getClient().request({
315
340
  url: this.response.url,
316
341
  method,
317
- data: method === "get" ? {} : data,
318
- params: method === "get" ? data : {},
342
+ data: method === "get" ? void 0 : data,
343
+ params: method === "get" ? data : void 0,
319
344
  headers: {
320
345
  ...options.headers ?? {},
321
346
  Accept: "text/html, application/xhtml+xml",
@@ -327,7 +352,7 @@
327
352
  "X-InertiaUI-Modal-Base-Url": baseUrl ?? ""
328
353
  }
329
354
  }).then((response2) => {
330
- this.updateProps(response2.data.props);
355
+ this.updateProps(parseResponseData(response2.data).props);
331
356
  options.onSuccess?.(response2);
332
357
  }).catch((error) => {
333
358
  options.onError?.(error);
@@ -359,9 +384,6 @@
359
384
  return typeof data === "object" && data !== null && "component" in data && typeof data.component === "string";
360
385
  };
361
386
  const pushFromResponseData = (responseData, config = {}, onClose = null, onAfterLeave = null) => {
362
- if (!resolveComponent) {
363
- return Promise.reject(new Error("resolveComponent not set"));
364
- }
365
387
  if (!isValidModalResponse(responseData)) {
366
388
  return Promise.reject(
367
389
  new Error(
@@ -369,7 +391,7 @@
369
391
  )
370
392
  );
371
393
  }
372
- return resolveComponent(responseData.component).then(
394
+ return react.router.resolveComponent(responseData.component).then(
373
395
  (component) => push(component, responseData, config, onClose, onAfterLeave)
374
396
  );
375
397
  };
@@ -448,11 +470,12 @@
448
470
  return;
449
471
  }
450
472
  const [url, data] = core.mergeDataIntoQueryString(method, href || "", payload, queryStringArrayFormat);
451
- const cachedResponse = getCachedResponse(url, method, data);
473
+ const cachedResponse = prefetchCache.get(ResponseCache.key(method, url, data));
452
474
  if (cachedResponse) {
475
+ const cachedData = parseResponseData(cachedResponse.data);
453
476
  onSuccess?.(cachedResponse);
454
- pushFromResponseData(cachedResponse.data, config, onClose, onAfterLeave).then((modal) => {
455
- updateBrowserUrl(cachedResponse.data.url, useBrowserHistory, cachedResponse.data);
477
+ pushFromResponseData(cachedData, config, onClose, onAfterLeave).then((modal) => {
478
+ updateBrowserUrl(cachedData.url, useBrowserHistory, cachedData);
456
479
  resolve(modal);
457
480
  }).catch(reject);
458
481
  return;
@@ -465,21 +488,22 @@
465
488
  Accept: "text/html, application/xhtml+xml",
466
489
  "X-Requested-With": "XMLHttpRequest",
467
490
  "X-Inertia": "true",
468
- "X-Inertia-Version": pageVersion ?? "",
491
+ "X-Inertia-Version": currentPageVersion ?? "",
469
492
  "X-InertiaUI-Modal": modalId,
470
493
  "X-InertiaUI-Modal-Base-Url": baseUrl ?? ""
471
494
  };
472
495
  onStart?.();
473
496
  react.progress?.start();
474
- Axios({
497
+ react.http.getClient().request({
475
498
  url,
476
499
  method,
477
500
  data,
478
501
  headers: requestHeaders
479
502
  }).then((response) => {
503
+ const responseData = parseResponseData(response.data);
480
504
  onSuccess?.(response);
481
- pushFromResponseData(response.data, config, onClose, onAfterLeave).then((modal) => {
482
- updateBrowserUrl(response.data.url, useBrowserHistory, response.data);
505
+ pushFromResponseData(responseData, config, onClose, onAfterLeave).then((modal) => {
506
+ updateBrowserUrl(responseData.url, useBrowserHistory, responseData);
483
507
  resolve(modal);
484
508
  }).catch(reject);
485
509
  }).catch((...args) => {
@@ -536,10 +560,7 @@
536
560
  const modalPropNames = ["closeButton", "closeExplicitly", "closeOnClickOutside", "maxWidth", "paddingClasses", "panelClasses", "position", "slideover"];
537
561
  const initFromPageProps = (pageProps) => {
538
562
  if (pageProps.initialPage) {
539
- pageVersion = pageProps.initialPage.version ?? null;
540
- }
541
- if (pageProps.resolveComponent) {
542
- resolveComponent = pageProps.resolveComponent;
563
+ currentPageVersion = pageProps.initialPage.version ?? null;
543
564
  }
544
565
  };
545
566
  const renderApp = (App, pageProps) => {
@@ -569,9 +590,19 @@
569
590
  const context = React.useContext(ModalStackContext);
570
591
  const $page = react.usePage();
571
592
  const pendingModalKeysRef = React.useRef(/* @__PURE__ */ new Set());
593
+ currentPageVersion = $page.version ?? null;
572
594
  const getModalKey = (modalData) => modalData.id || `${modalData.component}:${modalData.url}`;
573
595
  const isNavigatingRef = React.useRef(false);
574
- const initialModalStillOpenedRef = React.useRef(!!$page.props?._inertiaui_modal);
596
+ const pageRef = React.useRef($page);
597
+ pageRef.current = $page;
598
+ React.useLayoutEffect(() => react.http.onRequest((config) => {
599
+ const baseUrlValue = baseUrl ?? pageRef.current.props._inertiaui_modal?.baseUrl ?? null;
600
+ if (baseUrlValue) {
601
+ config.headers = config.headers ?? {};
602
+ config.headers["X-InertiaUI-Modal-Base-Url"] = baseUrlValue;
603
+ }
604
+ return config;
605
+ }), []);
575
606
  React.useEffect(() => react.router.on("start", () => isNavigatingRef.current = true), []);
576
607
  React.useEffect(() => react.router.on("finish", () => isNavigatingRef.current = false), []);
577
608
  React.useEffect(
@@ -585,7 +616,6 @@
585
616
  closingToBaseUrlTarget = null;
586
617
  context?.closeAll(true);
587
618
  baseUrl = null;
588
- initialModalStillOpenedRef.current = false;
589
619
  return;
590
620
  }
591
621
  closingToBaseUrlTarget = null;
@@ -593,13 +623,11 @@
593
623
  if (!modalOnBase) {
594
624
  context?.closeAll(true);
595
625
  baseUrl = null;
596
- initialModalStillOpenedRef.current = false;
597
626
  return;
598
627
  }
599
628
  if (!vanilla.sameUrlPath(pageUrl, modalOnBase.url)) {
600
629
  context?.closeAll(true);
601
630
  baseUrl = null;
602
- initialModalStillOpenedRef.current = false;
603
631
  return;
604
632
  }
605
633
  const modalKey = getModalKey(modalOnBase);
@@ -619,6 +647,7 @@
619
647
  console.error("No base url in modal response data so cannot navigate back");
620
648
  return;
621
649
  }
650
+ baseUrl = null;
622
651
  if (!isNavigatingRef.current && typeof window !== "undefined" && window.location.href !== modalOnBase.baseUrl) {
623
652
  react.router.visit(modalOnBase.baseUrl, {
624
653
  preserveScroll: true,
@@ -631,17 +660,6 @@
631
660
  }),
632
661
  []
633
662
  );
634
- const axiosRequestInterceptor = (config) => {
635
- const baseUrlValue = baseUrl ?? (initialModalStillOpenedRef.current ? $page.props._inertiaui_modal?.baseUrl : null);
636
- if (baseUrlValue) {
637
- config.headers["X-InertiaUI-Modal-Base-Url"] = baseUrlValue;
638
- }
639
- return config;
640
- };
641
- React.useEffect(() => {
642
- const interceptorId = Axios.interceptors.request.use(axiosRequestInterceptor);
643
- return () => Axios.interceptors.request.eject(interceptorId);
644
- }, []);
645
663
  const previousModalRef = React.useRef(void 0);
646
664
  React.useEffect(() => {
647
665
  const newModal = $page.props?._inertiaui_modal;
@@ -755,7 +773,7 @@
755
773
  }, [modalContext]);
756
774
  const previousIsOpenRef = React.useRef(void 0);
757
775
  React.useEffect(() => {
758
- if (modalContext !== null) {
776
+ if (modalContext != null) {
759
777
  if (modalContext.isOpen) {
760
778
  onSuccess?.();
761
779
  } else if (previousIsOpenRef.current === true) {
@@ -766,7 +784,7 @@
766
784
  }, [modalContext?.isOpen]);
767
785
  const [rendered, setRendered] = React.useState(false);
768
786
  React.useEffect(() => {
769
- if (rendered && modalContext !== null && modalContext.isOpen) {
787
+ if (rendered && modalContext != null && modalContext.isOpen) {
770
788
  if (modalContext.onTopOfStack) {
771
789
  onFocus?.();
772
790
  } else {