react-instantsearch-core 7.0.2 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
2
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3
- **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
3
+
4
4
 
5
5
  - [react-instantsearch-core](#react-instantsearch-core)
6
6
  - [Installation](#installation)
@@ -19,7 +19,7 @@ React InstantSearch Core is an open-source UI library for React that lets you qu
19
19
  InstantSearch’s goal is to help you implement awesome search experiences as smoothly as possible by providing a [complete search ecosystem](https://algolia.com/doc/guides/getting-started/how-algolia-works/#the-full-ecosystem). InstantSearch tackles an important part of this vast goal by providing front-end primitives that you can assemble into unique search interfaces.
20
20
 
21
21
  <p align="center">
22
- <a href="https://codesandbox.io/s/github/algolia/instantsearch.js/tree/master/examples/react/default-themes" title="Edit on CodeSandbox">
22
+ <a href="https://codesandbox.io/s/github/algolia/instantsearch/tree/master/examples/react/default-themes" title="Edit on CodeSandbox">
23
23
  <img alt="Edit on CodeSandbox" src="https://codesandbox.io/static/img/play-codesandbox.svg">
24
24
  </a>
25
25
  </p>
@@ -65,7 +65,7 @@ To start contributing to code, you need to:
65
65
  1. [Clone the repository](https://help.github.com/articles/cloning-a-repository/)
66
66
  1. Install the dependencies: `yarn`
67
67
 
68
- Please read [our contribution process](https://github.com/algolia/instantsearch.js/blob/master/CONTRIBUTING.md) to learn more.
68
+ Please read [our contribution process](https://github.com/algolia/instantsearch/blob/master/CONTRIBUTING.md) to learn more.
69
69
 
70
70
  ## License
71
71
 
@@ -73,9 +73,9 @@ React InstantSearch is [MIT licensed](../../LICENSE).
73
73
 
74
74
  <!-- Links -->
75
75
 
76
- [contributing-bugreport]: https://github.com/algolia/instantsearch.js/issues/new?template=BUG_REPORT.yml&labels=triage,Library%3A%20React+InstantSearch
77
- [contributing-featurerequest]: https://github.com/algolia/instantsearch.js/discussions/new?category=ideas&labels=triage,Library%3A%20React+InstantSearch&title=Feature%20request%3A%20
78
- [contributing-newissue]: https://github.com/algolia/instantsearch.js/issues/new?labels=triage,Library%3A%20React+InstantSearch
79
- [contributing-label-easy]: https://github.com/algolia/instantsearch.js/issues?q=is%3Aopen+is%3Aissue+label%3A%22Difficulty%3A+Easy%22+label%3A%22Library%3A%20React+InstantSearch%22
80
- [contributing-label-bug]: https://github.com/algolia/instantsearch.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Bug%22+label%3A%22Library%3A%20React+InstantSearch%22
81
- [contributing-label-chore]: https://github.com/algolia/instantsearch.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Chore%22+label%3A%22Library%3A%20React+InstantSearch%22
76
+ [contributing-bugreport]: https://github.com/algolia/instantsearch/issues/new?template=BUG_REPORT.yml&labels=triage,Library%3A%20React+InstantSearch
77
+ [contributing-featurerequest]: https://github.com/algolia/instantsearch/discussions/new?category=ideas&labels=triage,Library%3A%20React+InstantSearch&title=Feature%20request%3A%20
78
+ [contributing-newissue]: https://github.com/algolia/instantsearch/issues/new?labels=triage,Library%3A%20React+InstantSearch
79
+ [contributing-label-easy]: https://github.com/algolia/instantsearch/issues?q=is%3Aopen+is%3Aissue+label%3A%22Difficulty%3A+Easy%22+label%3A%22Library%3A%20React+InstantSearch%22
80
+ [contributing-label-bug]: https://github.com/algolia/instantsearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Bug%22+label%3A%22Library%3A%20React+InstantSearch%22
81
+ [contributing-label-chore]: https://github.com/algolia/instantsearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Chore%22+label%3A%22Library%3A%20React+InstantSearch%22
@@ -100,7 +100,7 @@ function useConnector(connector) {
100
100
 
101
101
  // We get the widget render state by providing the same parameters as
102
102
  // InstantSearch provides to the widget's `render` method.
103
- // See https://github.com/algolia/instantsearch.js/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
103
+ // See https://github.com/algolia/instantsearch/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
104
104
  var _widget$getWidgetRend = widget.getWidgetRenderState({
105
105
  helper: helper,
106
106
  parent: parentIndex,
package/dist/cjs/index.js CHANGED
@@ -361,6 +361,54 @@ Object.keys(_useInstantSearch).forEach(function (key) {
361
361
  }
362
362
  });
363
363
  });
364
+ var _wrapPromiseWithState = require("./lib/wrapPromiseWithState");
365
+ Object.keys(_wrapPromiseWithState).forEach(function (key) {
366
+ if (key === "default" || key === "__esModule") return;
367
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
368
+ if (key in exports && exports[key] === _wrapPromiseWithState[key]) return;
369
+ Object.defineProperty(exports, key, {
370
+ enumerable: true,
371
+ get: function get() {
372
+ return _wrapPromiseWithState[key];
373
+ }
374
+ });
375
+ });
376
+ var _useInstantSearchContext = require("./lib/useInstantSearchContext");
377
+ Object.keys(_useInstantSearchContext).forEach(function (key) {
378
+ if (key === "default" || key === "__esModule") return;
379
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
380
+ if (key in exports && exports[key] === _useInstantSearchContext[key]) return;
381
+ Object.defineProperty(exports, key, {
382
+ enumerable: true,
383
+ get: function get() {
384
+ return _useInstantSearchContext[key];
385
+ }
386
+ });
387
+ });
388
+ var _useRSCContext = require("./lib/useRSCContext");
389
+ Object.keys(_useRSCContext).forEach(function (key) {
390
+ if (key === "default" || key === "__esModule") return;
391
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
392
+ if (key in exports && exports[key] === _useRSCContext[key]) return;
393
+ Object.defineProperty(exports, key, {
394
+ enumerable: true,
395
+ get: function get() {
396
+ return _useRSCContext[key];
397
+ }
398
+ });
399
+ });
400
+ var _InstantSearchRSCContext = require("./lib/InstantSearchRSCContext");
401
+ Object.keys(_InstantSearchRSCContext).forEach(function (key) {
402
+ if (key === "default" || key === "__esModule") return;
403
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
404
+ if (key in exports && exports[key] === _InstantSearchRSCContext[key]) return;
405
+ Object.defineProperty(exports, key, {
406
+ enumerable: true,
407
+ get: function get() {
408
+ return _InstantSearchRSCContext[key];
409
+ }
410
+ });
411
+ });
364
412
  var _server = require("./server");
365
413
  Object.keys(_server).forEach(function (key) {
366
414
  if (key === "default" || key === "__esModule") return;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.InstantSearchRSCContext = void 0;
7
+ var _react = require("react");
8
+ var InstantSearchRSCContext = /*#__PURE__*/(0, _react.createContext)(null);
9
+ exports.InstantSearchRSCContext = InstantSearchRSCContext;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.use = void 0;
8
+ var React = _interopRequireWildcard(require("react"));
9
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
10
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
11
+ var useKey = 'use';
12
+
13
+ // @TODO: Remove this file and import directly from React when available.
14
+ var use = React[useKey];
15
+ exports.use = use;
@@ -7,10 +7,11 @@ exports.useInstantSearchApi = useInstantSearchApi;
7
7
  var _InstantSearch = _interopRequireDefault(require("instantsearch.js/cjs/lib/InstantSearch"));
8
8
  var _react = require("react");
9
9
  var _shim = require("use-sync-external-store/shim");
10
- var _useInstantSearchServerContext = require("../lib/useInstantSearchServerContext");
11
- var _useInstantSearchSSRContext = require("../lib/useInstantSearchSSRContext");
12
10
  var _version = _interopRequireDefault(require("../version"));
13
11
  var _useForceUpdate = require("./useForceUpdate");
12
+ var _useInstantSearchServerContext = require("./useInstantSearchServerContext");
13
+ var _useInstantSearchSSRContext = require("./useInstantSearchSSRContext");
14
+ var _useRSCContext = require("./useRSCContext");
14
15
  var _warn = require("./warn");
15
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17
  var defaultUserAgents = ["react (".concat(_react.version, ")"), "react-instantsearch (".concat(_version.default, ")"), "react-instantsearch-core (".concat(_version.default, ")")];
@@ -22,8 +23,10 @@ function useInstantSearchApi(props) {
22
23
  var forceUpdate = (0, _useForceUpdate.useForceUpdate)();
23
24
  var serverContext = (0, _useInstantSearchServerContext.useInstantSearchServerContext)();
24
25
  var serverState = (0, _useInstantSearchSSRContext.useInstantSearchSSRContext)();
26
+ var waitingForResultsRef = (0, _useRSCContext.useRSCContext)();
25
27
  var initialResults = serverState === null || serverState === void 0 ? void 0 : serverState.initialResults;
26
28
  var prevPropsRef = (0, _react.useRef)(props);
29
+ var shouldRenderAtOnce = serverContext || initialResults || waitingForResultsRef;
27
30
  var searchRef = (0, _react.useRef)(null);
28
31
  // As we need to render on mount with SSR, using the local ref above in `StrictMode` will
29
32
  // create and start two instances of InstantSearch. To avoid this, we instead discard it and use
@@ -34,7 +37,7 @@ function useInstantSearchApi(props) {
34
37
  if (searchRef.current === null) {
35
38
  // We don't use the `instantsearch()` function because it comes with other
36
39
  // top-level APIs that we don't need.
37
- // See https://github.com/algolia/instantsearch.js/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
40
+ // See https://github.com/algolia/instantsearch/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
38
41
  var search = new _InstantSearch.default(props);
39
42
  search._schedule = function _schedule(cb) {
40
43
  search._schedule.queue.push(cb);
@@ -47,7 +50,7 @@ function useInstantSearchApi(props) {
47
50
  }, 0);
48
51
  };
49
52
  search._schedule.queue = [];
50
- if (serverContext || initialResults) {
53
+ if (shouldRenderAtOnce) {
51
54
  // InstantSearch.js has a private Initial Results API that lets us inject
52
55
  // results on the search instance.
53
56
  // On the server, we default the initial results to an empty object so that
@@ -61,7 +64,7 @@ function useInstantSearchApi(props) {
61
64
  // On the server, we start the search early to compute the search parameters.
62
65
  // On SSR, we start the search early to directly catch up with the lifecycle
63
66
  // and render.
64
- if (serverContext || initialResults) {
67
+ if (shouldRenderAtOnce) {
65
68
  search.start();
66
69
  }
67
70
  if (serverContext) {
@@ -72,6 +75,7 @@ function useInstantSearchApi(props) {
72
75
  });
73
76
  }
74
77
  warnNextRouter(props.routing);
78
+ warnNextAppDir(Boolean(waitingForResultsRef));
75
79
  searchRef.current = search;
76
80
  }
77
81
  {
@@ -179,6 +183,13 @@ function warnNextRouter(routing) {
179
183
  process.env.NODE_ENV === 'development' ? (0, _warn.warn)(isUsingNextRouter, "\nYou are using Next.js with InstantSearch without the \"react-instantsearch-router-nextjs\" package.\nThis package is recommended to make the routing work correctly with Next.js.\nPlease check its usage instructions: https://github.com/algolia/instantsearch/tree/master/packages/react-instantsearch-router-nextjs\n\nYou can ignore this warning if you are using a custom router that suits your needs, it won't be outputted in production builds.") : void 0;
180
184
  }
181
185
  }
186
+ function warnNextAppDir(isRscContextDefined) {
187
+ var _next;
188
+ if (!(process.env.NODE_ENV === 'development') || typeof window === 'undefined' || isRscContextDefined) {
189
+ return;
190
+ }
191
+ process.env.NODE_ENV === 'development' ? (0, _warn.warn)(Boolean((_next = window.next) === null || _next === void 0 ? void 0 : _next.appDir) === false, "\nWe've detected you are using Next.js with the App Router.\nWe released an **experimental** package called \"react-instantsearch-nextjs\" that makes SSR work with the App Router.\nPlease check its usage instructions: https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react/#with-nextjs\n\nThis warning will not be outputted in production builds.") : void 0;
192
+ }
182
193
 
183
194
  /**
184
195
  * Gets the version of Next.js if it is available in the `window` object,
@@ -186,6 +197,6 @@ function warnNextRouter(routing) {
186
197
  * which is either `nodejs` or `edge`.
187
198
  */
188
199
  function getNextVersion() {
189
- var _next, _process$env;
190
- return typeof window !== 'undefined' && ((_next = window.next) === null || _next === void 0 ? void 0 : _next.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
200
+ var _next2, _process$env;
201
+ return typeof window !== 'undefined' && ((_next2 = window.next) === null || _next2 === void 0 ? void 0 : _next2.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
191
202
  }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useRSCContext = useRSCContext;
7
+ var _react = require("react");
8
+ var _InstantSearchRSCContext = require("./InstantSearchRSCContext");
9
+ function useRSCContext() {
10
+ return (0, _react.useContext)(_InstantSearchRSCContext.InstantSearchRSCContext);
11
+ }
@@ -29,7 +29,7 @@ function useSearchResults() {
29
29
 
30
30
  // Results can be `null` when the first search is stalled.
31
31
  // In this case, we skip the update.
32
- // See: https://github.com/algolia/instantsearch.js/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
32
+ // See: https://github.com/algolia/instantsearch/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
33
33
  if (results !== null) {
34
34
  setSearchResults({
35
35
  results: results,
@@ -6,13 +6,17 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.useWidget = useWidget;
7
7
  var _react = require("react");
8
8
  var _dequal = require("./dequal");
9
+ var _use = require("./use");
9
10
  var _useInstantSearchContext = require("./useInstantSearchContext");
10
11
  var _useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect");
12
+ var _useRSCContext = require("./useRSCContext");
11
13
  function useWidget(_ref) {
14
+ var _waitingForResultsRef;
12
15
  var widget = _ref.widget,
13
16
  parentIndex = _ref.parentIndex,
14
17
  props = _ref.props,
15
18
  shouldSsr = _ref.shouldSsr;
19
+ var waitingForResultsRef = (0, _useRSCContext.useRSCContext)();
16
20
  var prevPropsRef = (0, _react.useRef)(props);
17
21
  (0, _react.useEffect)(function () {
18
22
  prevPropsRef.current = props;
@@ -72,7 +76,18 @@ function useWidget(_ref) {
72
76
  });
73
77
  };
74
78
  }, [parentIndex, widget, shouldAddWidgetEarly, search, props]);
75
- if (shouldAddWidgetEarly) {
79
+ if (shouldAddWidgetEarly || (waitingForResultsRef === null || waitingForResultsRef === void 0 ? void 0 : (_waitingForResultsRef = waitingForResultsRef.current) === null || _waitingForResultsRef === void 0 ? void 0 : _waitingForResultsRef.status) === 'pending') {
76
80
  parentIndex.addWidgets([widget]);
77
81
  }
82
+ if (typeof window === 'undefined' && waitingForResultsRef !== null && waitingForResultsRef !== void 0 && waitingForResultsRef.current &&
83
+ // We need the widgets contained in the index to be added before we trigger the search request.
84
+ widget.$$type !== 'ais.index') {
85
+ var _search$helper;
86
+ (0, _use.use)(waitingForResultsRef.current);
87
+ // If we made a second request because of DynamicWidgets, we need to wait for the second result,
88
+ // except for DynamicWidgets itself which needs to render its children after the first result.
89
+ if (widget.$$type !== 'ais.dynamicWidgets' && (_search$helper = search.helper) !== null && _search$helper !== void 0 && _search$helper.lastResults) {
90
+ (0, _use.use)(waitingForResultsRef.current);
91
+ }
92
+ }
78
93
  }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.wrapPromiseWithState = wrapPromiseWithState;
7
+ // This is needed in order to work with RSC Suspense, perhaps they will later provide a wrapper.
8
+
9
+ function isStatefulPromise(promise) {
10
+ return 'status' in promise;
11
+ }
12
+ function wrapPromiseWithState(promise) {
13
+ if (isStatefulPromise(promise)) {
14
+ return promise;
15
+ }
16
+ var pendingPromise = promise;
17
+ pendingPromise.status = 'pending';
18
+ pendingPromise.then(function (value) {
19
+ if (pendingPromise.status === 'pending') {
20
+ var fulfilledPromise = pendingPromise;
21
+ fulfilledPromise.status = 'fulfilled';
22
+ fulfilledPromise.value = value;
23
+ }
24
+ }, function (reason) {
25
+ if (pendingPromise.status === 'pending') {
26
+ var rejectedPromise = pendingPromise;
27
+ rejectedPromise.status = 'rejected';
28
+ rejectedPromise.reason = reason;
29
+ }
30
+ });
31
+ return promise;
32
+ }
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = '7.0.2';
7
+ var _default = '7.1.0';
8
8
  exports.default = _default;
@@ -94,7 +94,7 @@ export function useConnector(connector) {
94
94
 
95
95
  // We get the widget render state by providing the same parameters as
96
96
  // InstantSearch provides to the widget's `render` method.
97
- // See https://github.com/algolia/instantsearch.js/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
97
+ // See https://github.com/algolia/instantsearch/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
98
98
  var _widget$getWidgetRend = widget.getWidgetRenderState({
99
99
  helper: helper,
100
100
  parent: parentIndex,
@@ -28,4 +28,8 @@ export * from './connectors/useStats';
28
28
  export * from './connectors/useToggleRefinement';
29
29
  export * from './hooks/useConnector';
30
30
  export * from './hooks/useInstantSearch';
31
+ export * from './lib/wrapPromiseWithState';
32
+ export * from './lib/useInstantSearchContext';
33
+ export * from './lib/useRSCContext';
34
+ export * from './lib/InstantSearchRSCContext';
31
35
  export * from './server';
package/dist/es/index.js CHANGED
@@ -28,4 +28,8 @@ export * from "./connectors/useStats.js";
28
28
  export * from "./connectors/useToggleRefinement.js";
29
29
  export * from "./hooks/useConnector.js";
30
30
  export * from "./hooks/useInstantSearch.js";
31
+ export * from "./lib/wrapPromiseWithState.js";
32
+ export * from "./lib/useInstantSearchContext.js";
33
+ export * from "./lib/useRSCContext.js";
34
+ export * from "./lib/InstantSearchRSCContext.js";
31
35
  export * from "./server/index.js";
@@ -0,0 +1,4 @@
1
+ import type { PromiseWithState } from './wrapPromiseWithState';
2
+ import type { MutableRefObject } from 'react';
3
+ export type InstantSearchRSCContextApi = MutableRefObject<PromiseWithState<void> | null> | null;
4
+ export declare const InstantSearchRSCContext: import("react").Context<InstantSearchRSCContextApi>;
@@ -0,0 +1,2 @@
1
+ import { createContext } from 'react';
2
+ export var InstantSearchRSCContext = /*#__PURE__*/createContext(null);
@@ -0,0 +1,3 @@
1
+ type Use = <T>(promise: Promise<T>) => T;
2
+ export declare const use: Use;
3
+ export {};
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ var useKey = 'use';
3
+
4
+ // @TODO: Remove this file and import directly from React when available.
5
+ export var use = React[useKey];
@@ -1,10 +1,11 @@
1
1
  import InstantSearch from "instantsearch.js/es/lib/InstantSearch.js";
2
2
  import { useCallback, useRef, version as ReactVersion } from 'react';
3
3
  import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
4
- import { useInstantSearchServerContext } from "./useInstantSearchServerContext.js";
5
- import { useInstantSearchSSRContext } from "./useInstantSearchSSRContext.js";
6
4
  import version from "../version.js";
7
5
  import { useForceUpdate } from "./useForceUpdate.js";
6
+ import { useInstantSearchServerContext } from "./useInstantSearchServerContext.js";
7
+ import { useInstantSearchSSRContext } from "./useInstantSearchSSRContext.js";
8
+ import { useRSCContext } from "./useRSCContext.js";
8
9
  import { warn } from "./warn.js";
9
10
  var defaultUserAgents = ["react (".concat(ReactVersion, ")"), "react-instantsearch (".concat(version, ")"), "react-instantsearch-core (".concat(version, ")")];
10
11
  var serverUserAgent = "react-instantsearch-server (".concat(version, ")");
@@ -15,8 +16,10 @@ export function useInstantSearchApi(props) {
15
16
  var forceUpdate = useForceUpdate();
16
17
  var serverContext = useInstantSearchServerContext();
17
18
  var serverState = useInstantSearchSSRContext();
19
+ var waitingForResultsRef = useRSCContext();
18
20
  var initialResults = serverState === null || serverState === void 0 ? void 0 : serverState.initialResults;
19
21
  var prevPropsRef = useRef(props);
22
+ var shouldRenderAtOnce = serverContext || initialResults || waitingForResultsRef;
20
23
  var searchRef = useRef(null);
21
24
  // As we need to render on mount with SSR, using the local ref above in `StrictMode` will
22
25
  // create and start two instances of InstantSearch. To avoid this, we instead discard it and use
@@ -27,7 +30,7 @@ export function useInstantSearchApi(props) {
27
30
  if (searchRef.current === null) {
28
31
  // We don't use the `instantsearch()` function because it comes with other
29
32
  // top-level APIs that we don't need.
30
- // See https://github.com/algolia/instantsearch.js/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
33
+ // See https://github.com/algolia/instantsearch/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
31
34
  var search = new InstantSearch(props);
32
35
  search._schedule = function _schedule(cb) {
33
36
  search._schedule.queue.push(cb);
@@ -40,7 +43,7 @@ export function useInstantSearchApi(props) {
40
43
  }, 0);
41
44
  };
42
45
  search._schedule.queue = [];
43
- if (serverContext || initialResults) {
46
+ if (shouldRenderAtOnce) {
44
47
  // InstantSearch.js has a private Initial Results API that lets us inject
45
48
  // results on the search instance.
46
49
  // On the server, we default the initial results to an empty object so that
@@ -54,7 +57,7 @@ export function useInstantSearchApi(props) {
54
57
  // On the server, we start the search early to compute the search parameters.
55
58
  // On SSR, we start the search early to directly catch up with the lifecycle
56
59
  // and render.
57
- if (serverContext || initialResults) {
60
+ if (shouldRenderAtOnce) {
58
61
  search.start();
59
62
  }
60
63
  if (serverContext) {
@@ -65,6 +68,7 @@ export function useInstantSearchApi(props) {
65
68
  });
66
69
  }
67
70
  warnNextRouter(props.routing);
71
+ warnNextAppDir(Boolean(waitingForResultsRef));
68
72
  searchRef.current = search;
69
73
  }
70
74
  {
@@ -172,6 +176,13 @@ function warnNextRouter(routing) {
172
176
  process.env.NODE_ENV === 'development' ? warn(isUsingNextRouter, "\nYou are using Next.js with InstantSearch without the \"react-instantsearch-router-nextjs\" package.\nThis package is recommended to make the routing work correctly with Next.js.\nPlease check its usage instructions: https://github.com/algolia/instantsearch/tree/master/packages/react-instantsearch-router-nextjs\n\nYou can ignore this warning if you are using a custom router that suits your needs, it won't be outputted in production builds.") : void 0;
173
177
  }
174
178
  }
179
+ function warnNextAppDir(isRscContextDefined) {
180
+ var _next;
181
+ if (!(process.env.NODE_ENV === 'development') || typeof window === 'undefined' || isRscContextDefined) {
182
+ return;
183
+ }
184
+ process.env.NODE_ENV === 'development' ? warn(Boolean((_next = window.next) === null || _next === void 0 ? void 0 : _next.appDir) === false, "\nWe've detected you are using Next.js with the App Router.\nWe released an **experimental** package called \"react-instantsearch-nextjs\" that makes SSR work with the App Router.\nPlease check its usage instructions: https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react/#with-nextjs\n\nThis warning will not be outputted in production builds.") : void 0;
185
+ }
175
186
 
176
187
  /**
177
188
  * Gets the version of Next.js if it is available in the `window` object,
@@ -179,6 +190,6 @@ function warnNextRouter(routing) {
179
190
  * which is either `nodejs` or `edge`.
180
191
  */
181
192
  function getNextVersion() {
182
- var _next, _process$env;
183
- return typeof window !== 'undefined' && ((_next = window.next) === null || _next === void 0 ? void 0 : _next.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
193
+ var _next2, _process$env;
194
+ return typeof window !== 'undefined' && ((_next2 = window.next) === null || _next2 === void 0 ? void 0 : _next2.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
184
195
  }
@@ -0,0 +1 @@
1
+ export declare function useRSCContext(): import("./InstantSearchRSCContext").InstantSearchRSCContextApi;
@@ -0,0 +1,5 @@
1
+ import { useContext } from 'react';
2
+ import { InstantSearchRSCContext } from "./InstantSearchRSCContext.js";
3
+ export function useRSCContext() {
4
+ return useContext(InstantSearchRSCContext);
5
+ }
@@ -23,7 +23,7 @@ export function useSearchResults() {
23
23
 
24
24
  // Results can be `null` when the first search is stalled.
25
25
  // In this case, we skip the update.
26
- // See: https://github.com/algolia/instantsearch.js/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
26
+ // See: https://github.com/algolia/instantsearch/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
27
27
  if (results !== null) {
28
28
  setSearchResults({
29
29
  results: results,
@@ -1,12 +1,16 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import { dequal } from "./dequal.js";
3
+ import { use } from "./use.js";
3
4
  import { useInstantSearchContext } from "./useInstantSearchContext.js";
4
5
  import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
6
+ import { useRSCContext } from "./useRSCContext.js";
5
7
  export function useWidget(_ref) {
8
+ var _waitingForResultsRef;
6
9
  var widget = _ref.widget,
7
10
  parentIndex = _ref.parentIndex,
8
11
  props = _ref.props,
9
12
  shouldSsr = _ref.shouldSsr;
13
+ var waitingForResultsRef = useRSCContext();
10
14
  var prevPropsRef = useRef(props);
11
15
  useEffect(function () {
12
16
  prevPropsRef.current = props;
@@ -66,7 +70,18 @@ export function useWidget(_ref) {
66
70
  });
67
71
  };
68
72
  }, [parentIndex, widget, shouldAddWidgetEarly, search, props]);
69
- if (shouldAddWidgetEarly) {
73
+ if (shouldAddWidgetEarly || (waitingForResultsRef === null || waitingForResultsRef === void 0 ? void 0 : (_waitingForResultsRef = waitingForResultsRef.current) === null || _waitingForResultsRef === void 0 ? void 0 : _waitingForResultsRef.status) === 'pending') {
70
74
  parentIndex.addWidgets([widget]);
71
75
  }
76
+ if (typeof window === 'undefined' && waitingForResultsRef !== null && waitingForResultsRef !== void 0 && waitingForResultsRef.current &&
77
+ // We need the widgets contained in the index to be added before we trigger the search request.
78
+ widget.$$type !== 'ais.index') {
79
+ var _search$helper;
80
+ use(waitingForResultsRef.current);
81
+ // If we made a second request because of DynamicWidgets, we need to wait for the second result,
82
+ // except for DynamicWidgets itself which needs to render its children after the first result.
83
+ if (widget.$$type !== 'ais.dynamicWidgets' && (_search$helper = search.helper) !== null && _search$helper !== void 0 && _search$helper.lastResults) {
84
+ use(waitingForResultsRef.current);
85
+ }
86
+ }
72
87
  }
@@ -0,0 +1,14 @@
1
+ interface PendingPromise<TValue> extends Promise<TValue> {
2
+ status: 'pending';
3
+ }
4
+ interface FulfilledPromise<TValue> extends Promise<TValue> {
5
+ status: 'fulfilled';
6
+ value: TValue;
7
+ }
8
+ interface RejectedPromise<TValue> extends Promise<TValue> {
9
+ status: 'rejected';
10
+ reason: unknown;
11
+ }
12
+ export type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;
13
+ export declare function wrapPromiseWithState<TValue>(promise: Promise<TValue>): PromiseWithState<TValue>;
14
+ export {};
@@ -0,0 +1,26 @@
1
+ // This is needed in order to work with RSC Suspense, perhaps they will later provide a wrapper.
2
+
3
+ function isStatefulPromise(promise) {
4
+ return 'status' in promise;
5
+ }
6
+ export function wrapPromiseWithState(promise) {
7
+ if (isStatefulPromise(promise)) {
8
+ return promise;
9
+ }
10
+ var pendingPromise = promise;
11
+ pendingPromise.status = 'pending';
12
+ pendingPromise.then(function (value) {
13
+ if (pendingPromise.status === 'pending') {
14
+ var fulfilledPromise = pendingPromise;
15
+ fulfilledPromise.status = 'fulfilled';
16
+ fulfilledPromise.value = value;
17
+ }
18
+ }, function (reason) {
19
+ if (pendingPromise.status === 'pending') {
20
+ var rejectedPromise = pendingPromise;
21
+ rejectedPromise.status = 'rejected';
22
+ rejectedPromise.reason = reason;
23
+ }
24
+ });
25
+ return promise;
26
+ }
@@ -1,2 +1,2 @@
1
- declare const _default: "7.0.2";
1
+ declare const _default: "7.1.0";
2
2
  export default _default;
@@ -1 +1 @@
1
- export default '7.0.2';
1
+ export default '7.1.0';