@abcagency/hc-ui-components 1.7.4 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/components/HireControlMap.js +2 -1
  2. package/dist/components/HireControlMap.js.map +1 -1
  3. package/dist/components/containers/accordions/map-accordion-item-container.js +3 -1
  4. package/dist/components/containers/accordions/map-accordion-item-container.js.map +1 -1
  5. package/dist/components/containers/filter/commute-container.js +11 -3
  6. package/dist/components/containers/filter/commute-container.js.map +1 -1
  7. package/dist/components/containers/maps/map-container.js +2 -0
  8. package/dist/components/containers/maps/map-container.js.map +1 -1
  9. package/dist/components/containers/maps/map-list-container.js +34 -3
  10. package/dist/components/containers/maps/map-list-container.js.map +1 -1
  11. package/dist/components/modules/filter/commute.js +3 -1
  12. package/dist/components/modules/filter/commute.js.map +1 -1
  13. package/dist/components/modules/filter/index.js +1 -0
  14. package/dist/components/modules/filter/index.js.map +1 -1
  15. package/dist/components/modules/filter/item.js +1 -0
  16. package/dist/components/modules/filter/item.js.map +1 -1
  17. package/dist/components/modules/list/list-item/list-item.js +85 -14
  18. package/dist/components/modules/list/list-item/list-item.js.map +1 -1
  19. package/dist/contexts/mapListContext.js +7 -1
  20. package/dist/contexts/mapListContext.js.map +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/node_modules/@algolia/requester-node-http/dist/requester.http.js +82 -0
  23. package/dist/node_modules/@algolia/requester-node-http/dist/requester.http.js.map +1 -0
  24. package/dist/node_modules/algoliasearch/dist/lite/builds/node.js +269 -0
  25. package/dist/node_modules/algoliasearch/dist/lite/builds/node.js.map +1 -0
  26. package/package.json +4 -1
  27. package/src/components/HireControlMap.js +0 -2
  28. package/src/components/containers/accordions/map-accordion-item-container.js +3 -1
  29. package/src/components/containers/filter/commute-container.js +11 -3
  30. package/src/components/containers/maps/map-container.js +2 -0
  31. package/src/components/containers/maps/map-list-container.js +30 -3
  32. package/src/components/modules/filter/commute.js +7 -5
  33. package/src/components/modules/filter/index.js +2 -0
  34. package/src/components/modules/filter/item.js +1 -0
  35. package/src/components/modules/list/list-item/list-item.jsx +97 -24
  36. package/src/contexts/mapListContext.tsx +5 -1
@@ -0,0 +1,269 @@
1
+ import { createHttpRequester } from '../../../../@algolia/requester-node-http/dist/requester.http.js';
2
+ import { createNullLogger, createNullCache, createMemoryCache, createTransporter, getAlgoliaAgent, shuffle, createAuth } from '../../../../@algolia/client-common/dist/common.js';
3
+
4
+ // lite/builds/node.ts
5
+ var apiClientVersion = "5.40.0";
6
+ function getDefaultHosts(appId) {
7
+ return [
8
+ {
9
+ url: `${appId}-dsn.algolia.net`,
10
+ accept: "read",
11
+ protocol: "https"
12
+ },
13
+ {
14
+ url: `${appId}.algolia.net`,
15
+ accept: "write",
16
+ protocol: "https"
17
+ }
18
+ ].concat(
19
+ shuffle([
20
+ {
21
+ url: `${appId}-1.algolianet.com`,
22
+ accept: "readWrite",
23
+ protocol: "https"
24
+ },
25
+ {
26
+ url: `${appId}-2.algolianet.com`,
27
+ accept: "readWrite",
28
+ protocol: "https"
29
+ },
30
+ {
31
+ url: `${appId}-3.algolianet.com`,
32
+ accept: "readWrite",
33
+ protocol: "https"
34
+ }
35
+ ])
36
+ );
37
+ }
38
+ function createLiteClient({
39
+ appId: appIdOption,
40
+ apiKey: apiKeyOption,
41
+ authMode,
42
+ algoliaAgents,
43
+ ...options
44
+ }) {
45
+ const auth = createAuth(appIdOption, apiKeyOption, authMode);
46
+ const transporter = createTransporter({
47
+ hosts: getDefaultHosts(appIdOption),
48
+ ...options,
49
+ algoliaAgent: getAlgoliaAgent({
50
+ algoliaAgents,
51
+ client: "Lite",
52
+ version: apiClientVersion
53
+ }),
54
+ baseHeaders: {
55
+ "content-type": "text/plain",
56
+ ...auth.headers(),
57
+ ...options.baseHeaders
58
+ },
59
+ baseQueryParameters: {
60
+ ...auth.queryParameters(),
61
+ ...options.baseQueryParameters
62
+ }
63
+ });
64
+ return {
65
+ transporter,
66
+ /**
67
+ * The `appId` currently in use.
68
+ */
69
+ appId: appIdOption,
70
+ /**
71
+ * The `apiKey` currently in use.
72
+ */
73
+ apiKey: apiKeyOption,
74
+ /**
75
+ * Clears the cache of the transporter for the `requestsCache` and `responsesCache` properties.
76
+ */
77
+ clearCache() {
78
+ return Promise.all([transporter.requestsCache.clear(), transporter.responsesCache.clear()]).then(() => void 0);
79
+ },
80
+ /**
81
+ * Get the value of the `algoliaAgent`, used by our libraries internally and telemetry system.
82
+ */
83
+ get _ua() {
84
+ return transporter.algoliaAgent.value;
85
+ },
86
+ /**
87
+ * Adds a `segment` to the `x-algolia-agent` sent with every requests.
88
+ *
89
+ * @param segment - The algolia agent (user-agent) segment to add.
90
+ * @param version - The version of the agent.
91
+ */
92
+ addAlgoliaAgent(segment, version) {
93
+ transporter.algoliaAgent.add({ segment, version });
94
+ },
95
+ /**
96
+ * Helper method to switch the API key used to authenticate the requests.
97
+ *
98
+ * @param params - Method params.
99
+ * @param params.apiKey - The new API Key to use.
100
+ */
101
+ setClientApiKey({ apiKey }) {
102
+ if (!authMode || authMode === "WithinHeaders") {
103
+ transporter.baseHeaders["x-algolia-api-key"] = apiKey;
104
+ } else {
105
+ transporter.baseQueryParameters["x-algolia-api-key"] = apiKey;
106
+ }
107
+ },
108
+ /**
109
+ * Helper: calls the `search` method but with certainty that we will only request Algolia records (hits) and not facets.
110
+ * Disclaimer: We don't assert that the parameters you pass to this method only contains `hits` requests to prevent impacting search performances, this helper is purely for typing purposes.
111
+ *
112
+ * @summary Search multiple indices for `hits`.
113
+ * @param searchMethodParams - Query requests and strategies. Results will be received in the same order as the queries.
114
+ * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
115
+ */
116
+ searchForHits(searchMethodParams, requestOptions) {
117
+ return this.search(searchMethodParams, requestOptions);
118
+ },
119
+ /**
120
+ * Helper: calls the `search` method but with certainty that we will only request Algolia facets and not records (hits).
121
+ * Disclaimer: We don't assert that the parameters you pass to this method only contains `facets` requests to prevent impacting search performances, this helper is purely for typing purposes.
122
+ *
123
+ * @summary Search multiple indices for `facets`.
124
+ * @param searchMethodParams - Query requests and strategies. Results will be received in the same order as the queries.
125
+ * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
126
+ */
127
+ searchForFacets(searchMethodParams, requestOptions) {
128
+ return this.search(searchMethodParams, requestOptions);
129
+ },
130
+ /**
131
+ * This method lets you send requests to the Algolia REST API.
132
+ * @param customPost - The customPost object.
133
+ * @param customPost.path - Path of the endpoint, for example `1/newFeature`.
134
+ * @param customPost.parameters - Query parameters to apply to the current query.
135
+ * @param customPost.body - Parameters to send with the custom request.
136
+ * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
137
+ */
138
+ customPost({ path, parameters, body }, requestOptions) {
139
+ if (!path) {
140
+ throw new Error("Parameter `path` is required when calling `customPost`.");
141
+ }
142
+ const requestPath = "/{path}".replace("{path}", path);
143
+ const headers = {};
144
+ const queryParameters = parameters ? parameters : {};
145
+ const request = {
146
+ method: "POST",
147
+ path: requestPath,
148
+ queryParameters,
149
+ headers,
150
+ data: body ? body : {}
151
+ };
152
+ return transporter.request(request, requestOptions);
153
+ },
154
+ /**
155
+ * Retrieves recommendations from selected AI models.
156
+ *
157
+ * Required API Key ACLs:
158
+ * - search
159
+ * @param getRecommendationsParams - The getRecommendationsParams object.
160
+ * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
161
+ */
162
+ getRecommendations(getRecommendationsParams, requestOptions) {
163
+ if (getRecommendationsParams && Array.isArray(getRecommendationsParams)) {
164
+ const newSignatureRequest = {
165
+ requests: getRecommendationsParams
166
+ };
167
+ getRecommendationsParams = newSignatureRequest;
168
+ }
169
+ if (!getRecommendationsParams) {
170
+ throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");
171
+ }
172
+ if (!getRecommendationsParams.requests) {
173
+ throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");
174
+ }
175
+ const requestPath = "/1/indexes/*/recommendations";
176
+ const headers = {};
177
+ const queryParameters = {};
178
+ const request = {
179
+ method: "POST",
180
+ path: requestPath,
181
+ queryParameters,
182
+ headers,
183
+ data: getRecommendationsParams,
184
+ useReadTransporter: true,
185
+ cacheable: true
186
+ };
187
+ return transporter.request(request, requestOptions);
188
+ },
189
+ /**
190
+ * Sends multiple search requests to one or more indices. This can be useful in these cases: - Different indices for different purposes, such as, one index for products, another one for marketing content. - Multiple searches to the same index—for example, with different filters. Use the helper `searchForHits` or `searchForFacets` to get the results in a more convenient format, if you already know the return type you want.
191
+ *
192
+ * Required API Key ACLs:
193
+ * - search
194
+ * @param searchMethodParams - Muli-search request body. Results are returned in the same order as the requests.
195
+ * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
196
+ */
197
+ search(searchMethodParams, requestOptions) {
198
+ if (searchMethodParams && Array.isArray(searchMethodParams)) {
199
+ const newSignatureRequest = {
200
+ requests: searchMethodParams.map(({ params, ...legacyRequest }) => {
201
+ if (legacyRequest.type === "facet") {
202
+ return {
203
+ ...legacyRequest,
204
+ ...params,
205
+ type: "facet"
206
+ };
207
+ }
208
+ return {
209
+ ...legacyRequest,
210
+ ...params,
211
+ facet: void 0,
212
+ maxFacetHits: void 0,
213
+ facetQuery: void 0
214
+ };
215
+ })
216
+ };
217
+ searchMethodParams = newSignatureRequest;
218
+ }
219
+ if (!searchMethodParams) {
220
+ throw new Error("Parameter `searchMethodParams` is required when calling `search`.");
221
+ }
222
+ if (!searchMethodParams.requests) {
223
+ throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");
224
+ }
225
+ const requestPath = "/1/indexes/*/queries";
226
+ const headers = {};
227
+ const queryParameters = {};
228
+ const request = {
229
+ method: "POST",
230
+ path: requestPath,
231
+ queryParameters,
232
+ headers,
233
+ data: searchMethodParams,
234
+ useReadTransporter: true,
235
+ cacheable: true
236
+ };
237
+ return transporter.request(request, requestOptions);
238
+ }
239
+ };
240
+ }
241
+
242
+ // lite/builds/node.ts
243
+ function liteClient(appId, apiKey, options) {
244
+ if (!appId || typeof appId !== "string") {
245
+ throw new Error("`appId` is missing.");
246
+ }
247
+ if (!apiKey || typeof apiKey !== "string") {
248
+ throw new Error("`apiKey` is missing.");
249
+ }
250
+ return createLiteClient({
251
+ appId,
252
+ apiKey,
253
+ timeouts: {
254
+ connect: 2e3,
255
+ read: 5e3,
256
+ write: 3e4
257
+ },
258
+ logger: createNullLogger(),
259
+ requester: createHttpRequester(),
260
+ algoliaAgents: [{ segment: "Node.js", version: process.versions.node }],
261
+ responsesCache: createNullCache(),
262
+ requestsCache: createNullCache(),
263
+ hostsCache: createMemoryCache(),
264
+ ...options
265
+ });
266
+ }
267
+
268
+ export { apiClientVersion, liteClient };
269
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sources":["../../../../../../node_modules/algoliasearch/dist/lite/builds/node.js"],"sourcesContent":["// lite/builds/node.ts\nimport { createHttpRequester } from \"@algolia/requester-node-http\";\nimport { createMemoryCache, createNullCache, createNullLogger } from \"@algolia/client-common\";\n\n// lite/src/liteClient.ts\nimport { createAuth, createTransporter, getAlgoliaAgent, shuffle } from \"@algolia/client-common\";\nvar apiClientVersion = \"5.40.0\";\nfunction getDefaultHosts(appId) {\n return [\n {\n url: `${appId}-dsn.algolia.net`,\n accept: \"read\",\n protocol: \"https\"\n },\n {\n url: `${appId}.algolia.net`,\n accept: \"write\",\n protocol: \"https\"\n }\n ].concat(\n shuffle([\n {\n url: `${appId}-1.algolianet.com`,\n accept: \"readWrite\",\n protocol: \"https\"\n },\n {\n url: `${appId}-2.algolianet.com`,\n accept: \"readWrite\",\n protocol: \"https\"\n },\n {\n url: `${appId}-3.algolianet.com`,\n accept: \"readWrite\",\n protocol: \"https\"\n }\n ])\n );\n}\nfunction createLiteClient({\n appId: appIdOption,\n apiKey: apiKeyOption,\n authMode,\n algoliaAgents,\n ...options\n}) {\n const auth = createAuth(appIdOption, apiKeyOption, authMode);\n const transporter = createTransporter({\n hosts: getDefaultHosts(appIdOption),\n ...options,\n algoliaAgent: getAlgoliaAgent({\n algoliaAgents,\n client: \"Lite\",\n version: apiClientVersion\n }),\n baseHeaders: {\n \"content-type\": \"text/plain\",\n ...auth.headers(),\n ...options.baseHeaders\n },\n baseQueryParameters: {\n ...auth.queryParameters(),\n ...options.baseQueryParameters\n }\n });\n return {\n transporter,\n /**\n * The `appId` currently in use.\n */\n appId: appIdOption,\n /**\n * The `apiKey` currently in use.\n */\n apiKey: apiKeyOption,\n /**\n * Clears the cache of the transporter for the `requestsCache` and `responsesCache` properties.\n */\n clearCache() {\n return Promise.all([transporter.requestsCache.clear(), transporter.responsesCache.clear()]).then(() => void 0);\n },\n /**\n * Get the value of the `algoliaAgent`, used by our libraries internally and telemetry system.\n */\n get _ua() {\n return transporter.algoliaAgent.value;\n },\n /**\n * Adds a `segment` to the `x-algolia-agent` sent with every requests.\n *\n * @param segment - The algolia agent (user-agent) segment to add.\n * @param version - The version of the agent.\n */\n addAlgoliaAgent(segment, version) {\n transporter.algoliaAgent.add({ segment, version });\n },\n /**\n * Helper method to switch the API key used to authenticate the requests.\n *\n * @param params - Method params.\n * @param params.apiKey - The new API Key to use.\n */\n setClientApiKey({ apiKey }) {\n if (!authMode || authMode === \"WithinHeaders\") {\n transporter.baseHeaders[\"x-algolia-api-key\"] = apiKey;\n } else {\n transporter.baseQueryParameters[\"x-algolia-api-key\"] = apiKey;\n }\n },\n /**\n * Helper: calls the `search` method but with certainty that we will only request Algolia records (hits) and not facets.\n * Disclaimer: We don't assert that the parameters you pass to this method only contains `hits` requests to prevent impacting search performances, this helper is purely for typing purposes.\n *\n * @summary Search multiple indices for `hits`.\n * @param searchMethodParams - Query requests and strategies. Results will be received in the same order as the queries.\n * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.\n */\n searchForHits(searchMethodParams, requestOptions) {\n return this.search(searchMethodParams, requestOptions);\n },\n /**\n * Helper: calls the `search` method but with certainty that we will only request Algolia facets and not records (hits).\n * Disclaimer: We don't assert that the parameters you pass to this method only contains `facets` requests to prevent impacting search performances, this helper is purely for typing purposes.\n *\n * @summary Search multiple indices for `facets`.\n * @param searchMethodParams - Query requests and strategies. Results will be received in the same order as the queries.\n * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.\n */\n searchForFacets(searchMethodParams, requestOptions) {\n return this.search(searchMethodParams, requestOptions);\n },\n /**\n * This method lets you send requests to the Algolia REST API.\n * @param customPost - The customPost object.\n * @param customPost.path - Path of the endpoint, for example `1/newFeature`.\n * @param customPost.parameters - Query parameters to apply to the current query.\n * @param customPost.body - Parameters to send with the custom request.\n * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.\n */\n customPost({ path, parameters, body }, requestOptions) {\n if (!path) {\n throw new Error(\"Parameter `path` is required when calling `customPost`.\");\n }\n const requestPath = \"/{path}\".replace(\"{path}\", path);\n const headers = {};\n const queryParameters = parameters ? parameters : {};\n const request = {\n method: \"POST\",\n path: requestPath,\n queryParameters,\n headers,\n data: body ? body : {}\n };\n return transporter.request(request, requestOptions);\n },\n /**\n * Retrieves recommendations from selected AI models.\n *\n * Required API Key ACLs:\n * - search\n * @param getRecommendationsParams - The getRecommendationsParams object.\n * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.\n */\n getRecommendations(getRecommendationsParams, requestOptions) {\n if (getRecommendationsParams && Array.isArray(getRecommendationsParams)) {\n const newSignatureRequest = {\n requests: getRecommendationsParams\n };\n getRecommendationsParams = newSignatureRequest;\n }\n if (!getRecommendationsParams) {\n throw new Error(\"Parameter `getRecommendationsParams` is required when calling `getRecommendations`.\");\n }\n if (!getRecommendationsParams.requests) {\n throw new Error(\"Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.\");\n }\n const requestPath = \"/1/indexes/*/recommendations\";\n const headers = {};\n const queryParameters = {};\n const request = {\n method: \"POST\",\n path: requestPath,\n queryParameters,\n headers,\n data: getRecommendationsParams,\n useReadTransporter: true,\n cacheable: true\n };\n return transporter.request(request, requestOptions);\n },\n /**\n * Sends multiple search requests to one or more indices. This can be useful in these cases: - Different indices for different purposes, such as, one index for products, another one for marketing content. - Multiple searches to the same index—for example, with different filters. Use the helper `searchForHits` or `searchForFacets` to get the results in a more convenient format, if you already know the return type you want.\n *\n * Required API Key ACLs:\n * - search\n * @param searchMethodParams - Muli-search request body. Results are returned in the same order as the requests.\n * @param requestOptions - The requestOptions to send along with the query, they will be merged with the transporter requestOptions.\n */\n search(searchMethodParams, requestOptions) {\n if (searchMethodParams && Array.isArray(searchMethodParams)) {\n const newSignatureRequest = {\n requests: searchMethodParams.map(({ params, ...legacyRequest }) => {\n if (legacyRequest.type === \"facet\") {\n return {\n ...legacyRequest,\n ...params,\n type: \"facet\"\n };\n }\n return {\n ...legacyRequest,\n ...params,\n facet: void 0,\n maxFacetHits: void 0,\n facetQuery: void 0\n };\n })\n };\n searchMethodParams = newSignatureRequest;\n }\n if (!searchMethodParams) {\n throw new Error(\"Parameter `searchMethodParams` is required when calling `search`.\");\n }\n if (!searchMethodParams.requests) {\n throw new Error(\"Parameter `searchMethodParams.requests` is required when calling `search`.\");\n }\n const requestPath = \"/1/indexes/*/queries\";\n const headers = {};\n const queryParameters = {};\n const request = {\n method: \"POST\",\n path: requestPath,\n queryParameters,\n headers,\n data: searchMethodParams,\n useReadTransporter: true,\n cacheable: true\n };\n return transporter.request(request, requestOptions);\n }\n };\n}\n\n// lite/builds/node.ts\nfunction liteClient(appId, apiKey, options) {\n if (!appId || typeof appId !== \"string\") {\n throw new Error(\"`appId` is missing.\");\n }\n if (!apiKey || typeof apiKey !== \"string\") {\n throw new Error(\"`apiKey` is missing.\");\n }\n return createLiteClient({\n appId,\n apiKey,\n timeouts: {\n connect: 2e3,\n read: 5e3,\n write: 3e4\n },\n logger: createNullLogger(),\n requester: createHttpRequester(),\n algoliaAgents: [{ segment: \"Node.js\", version: process.versions.node }],\n responsesCache: createNullCache(),\n requestsCache: createNullCache(),\n hostsCache: createMemoryCache(),\n ...options\n });\n}\nexport {\n apiClientVersion,\n liteClient\n};\n//# sourceMappingURL=node.js.map"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@abcagency/hc-ui-components",
3
- "version": "1.7.4",
3
+ "version": "1.7.5",
4
4
  "description": "UI Components for HireControl",
5
5
  "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "sideEffects": false,
6
9
  "files": [
7
10
  "dist",
8
11
  "src"
@@ -16,8 +16,6 @@ import { getMapConfig } from '~/services/configService';
16
16
  import { setClientAuthKey } from '~/clientToken.js';
17
17
  import { initializeAlgoliaSearch } from '~/util/algoliaSearchUtil';
18
18
 
19
- import '../styles/components.css';
20
-
21
19
  // Libraries for Google Maps
22
20
  const LIBRARIES = ['places'];
23
21
 
@@ -21,7 +21,9 @@ const MapAccordionItemContainer = ({
21
21
 
22
22
  const setSelectedItemAndZoomMap = (item, isActive) => {
23
23
  if (isActive) {
24
- localStorage.removeItem("selectedListItem");
24
+ if (typeof window !== 'undefined') {
25
+ localStorage.removeItem("selectedListItem");
26
+ }
25
27
  selectItem(null, null, 9, { lat: 39.8283, lng: -98.5795 });
26
28
  } else {
27
29
  setStorageObject("selectedListItem", item);
@@ -23,15 +23,19 @@ const FilterCommuteContainer = ({ className }) => {
23
23
  useEffect(() => {
24
24
  if (commuteLocation !== null && commuteLocation !== '') return;
25
25
  setIsCurrentLocation(false);
26
- localStorage.removeItem('isCurrentLocation');
27
- localStorage.removeItem('selectedCommute');
26
+ if (typeof window !== 'undefined') {
27
+ localStorage.removeItem('isCurrentLocation');
28
+ localStorage.removeItem('selectedCommute');
29
+ }
28
30
  setSelected("");
29
31
  }, [commuteLocation]);
30
32
 
31
33
  const handleSelect = async (val, isCurrLocation = false) => {
32
34
  setValue(val, false);
33
35
  setSelected(val);
34
- localStorage.setItem('selectedCommute', val);
36
+ if (typeof window !== 'undefined') {
37
+ localStorage.setItem('selectedCommute', val);
38
+ }
35
39
  clearSuggestions();
36
40
  if (isCurrLocation) return;
37
41
  try {
@@ -45,6 +49,10 @@ const FilterCommuteContainer = ({ className }) => {
45
49
  };
46
50
 
47
51
  const fetchLocation = () => {
52
+ if (typeof window === 'undefined' || typeof navigator === 'undefined') {
53
+ console.error("Geolocation is not available in this environment.");
54
+ return;
55
+ }
48
56
  if (!navigator.geolocation) {
49
57
  console.error("Geolocation is not supported by this browser.");
50
58
  return;
@@ -145,6 +145,7 @@ const MapContainer = ({ markerConfigs, infoWindowClasses, clusterGridSize = 60 }
145
145
 
146
146
  const fitBounds = (map, overload = false) => {
147
147
  if ((mapInteracted === false || overload) && mapItems != null) {
148
+ if (typeof window === 'undefined' || !window.google) return;
148
149
  const bounds = new window.google.maps.LatLngBounds();
149
150
 
150
151
  mapItems.forEach(item => {
@@ -229,6 +230,7 @@ const MapContainer = ({ markerConfigs, infoWindowClasses, clusterGridSize = 60 }
229
230
  }
230
231
 
231
232
  setTimeout(() => {
233
+ if (typeof window === 'undefined' || !window.google) return;
232
234
  const bounds = new window.google.maps.LatLngBounds();
233
235
 
234
236
  markers.forEach(marker => {
@@ -1,10 +1,22 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect, lazy, Suspense } from 'react';
2
2
 
3
3
  import List from '~/components/containers/list/item-list-container';
4
- import Map from '~/components/containers/maps/map-container';
5
4
  import Filter from '~/components/containers/filter/filter-container';
6
5
  import MapList from '~/components/modules/maps/map-list';
7
6
 
7
+ // Dynamically import the Map container (Google Maps is heavy)
8
+ const Map = lazy(() => import('~/components/containers/maps/map-container'));
9
+
10
+ // Loading placeholder that maintains layout
11
+ const MapLoadingPlaceholder = () => (
12
+ <div className="hc-w-full hc-h-full hc-bg-gray-100 hc-flex hc-items-center hc-justify-center">
13
+ <div className="hc-text-center hc-p-8">
14
+ <div className="hc-animate-spin hc-rounded-full hc-h-12 hc-w-12 hc-border-b-2 hc-border-gray-900 hc-mx-auto"></div>
15
+ <p className="hc-mt-4 hc-text-gray-600">Loading map...</p>
16
+ </div>
17
+ </div>
18
+ );
19
+
8
20
  const MapListContainer = ({
9
21
  loading = false,
10
22
  containerStyle,
@@ -18,6 +30,12 @@ const MapListContainer = ({
18
30
  placeMappings,
19
31
  mapPosition
20
32
  }) => {
33
+ const [isClient, setIsClient] = useState(false);
34
+
35
+ // Only load map on client side
36
+ useEffect(() => {
37
+ setIsClient(true);
38
+ }, []);
21
39
 
22
40
  const listProps = {
23
41
  fieldsShown,
@@ -36,13 +54,22 @@ const MapListContainer = ({
36
54
  showMap
37
55
  };
38
56
 
57
+ // Render map only after client-side hydration
58
+ const mapComponent = isClient && showMap ? (
59
+ <Suspense fallback={<MapLoadingPlaceholder />}>
60
+ <Map {...mapProps} />
61
+ </Suspense>
62
+ ) : (
63
+ showMap ? <MapLoadingPlaceholder /> : null
64
+ );
65
+
39
66
  return (
40
67
  <MapList
41
68
  showMap={showMap}
42
69
  containerStyle={containerStyle}
43
70
  loading={loading}
44
71
  list={<List {...listProps} />}
45
- map={<Map {...mapProps} />}
72
+ map={mapComponent}
46
73
  filter={<Filter showMap={showMap} className="md:hc-hidden" />}
47
74
  mapPosition={mapPosition}
48
75
  />
@@ -57,12 +57,14 @@ const FilterCommute = ({
57
57
  size="sqsm"
58
58
  onClick={() => {
59
59
  setIsCurrentLocation(!isCurrentLocation);
60
+ if (typeof window !== 'undefined') {
60
61
  localStorage.setItem('isCurrentLocation', !isCurrentLocation);
61
- if (isCurrentLocation || commuteLocation) {
62
- setCommuteLocation("");
63
- setSelected("");
64
- } else if (!commuteLocation) { fetchLocation(); }
65
- }}
62
+ }
63
+ if (isCurrentLocation || commuteLocation) {
64
+ setCommuteLocation("");
65
+ setSelected("");
66
+ } else if (!commuteLocation) { fetchLocation(); }
67
+ }}
66
68
 
67
69
  className=""
68
70
  >
@@ -23,6 +23,8 @@ const Filter = ({
23
23
  const transitionTimeoutRef = useRef(null);
24
24
 
25
25
  useEffect(() => {
26
+ if (typeof window === 'undefined') return;
27
+
26
28
  const checkOverflow = () => {
27
29
  if (contentRef.current) {
28
30
  // Add a small tolerance (5px) to avoid false positives from rounding/padding
@@ -28,6 +28,7 @@ const FilterItem = ({
28
28
  onClick={() =>
29
29
  {
30
30
  if(!isExternalLink) return;
31
+ if (typeof window === 'undefined') return;
31
32
  trackEvent(eventTypes.EXTERNAL_LINK_CLICKED, { link: externalLinkUrl });
32
33
  window.location.href = externalLinkUrl;
33
34
  }}
@@ -1,4 +1,4 @@
1
- import React, { forwardRef } from 'react';
1
+ import React, { forwardRef, useState, useEffect, useRef } from 'react';
2
2
  import Grid from '~/components/modules/grid';
3
3
  import Icon from '~/components/modules/icon';
4
4
  import FieldMapper from '~/components/modules/list/field-mapper-desktop';
@@ -19,35 +19,104 @@ const ListItem = forwardRef(
19
19
  favorites,
20
20
  includeFavorite = true,
21
21
  siteConfig,
22
- googleMapsApiKey,
22
+ index,
23
23
  ...props
24
24
  },
25
25
  ref
26
26
  ) => {
27
27
  const mapPinColor = !showMap ? null : siteConfig.colors.primary.replace("#", "");
28
28
 
29
- const handleClick = () => {
30
- if (onItemSelected) {
31
- onItemSelected(item);
32
- }
29
+ // Mobile detection for bandwidth optimization
30
+ const [isMobile, setIsMobile] = useState(false);
31
+
32
+ // Individual item loading based on scroll position
33
+ const [isMapLoaded, setIsMapLoaded] = useState(false);
34
+ const itemRef = useRef(null);
35
+
36
+ useEffect(() => {
37
+ if (typeof window === 'undefined') return;
38
+
39
+ const checkIsMobile = () => {
40
+ setIsMobile(window.innerWidth < 768); // md breakpoint in Tailwind
33
41
  };
34
- let isFavorite = favorites.includes(item.id);
35
-
36
- const handleFavouriteClick = (event, item) => {
37
- if(!includeFavorite)return;
38
- event.stopPropagation();
39
- let updatedFavorites;
40
- if (isFavorite) {
41
- updatedFavorites = favorites.filter(fav => fav !== item.id);
42
- } else {
43
- updatedFavorites = [...favorites, item.id];
42
+
43
+ checkIsMobile();
44
+ window.addEventListener('resize', checkIsMobile);
45
+
46
+ return () => window.removeEventListener('resize', checkIsMobile);
47
+ }, []);
48
+
49
+ // Load individual map when item comes into view
50
+ useEffect(() => {
51
+ if (typeof window === 'undefined') return;
52
+ if (!isMobile || !showMap || !itemRef.current || isMapLoaded) return;
53
+
54
+ const checkIfInView = () => {
55
+ if (!itemRef.current || isMapLoaded) return;
56
+
57
+ const rect = itemRef.current.getBoundingClientRect();
58
+ const windowHeight = window.innerHeight;
59
+
60
+ // Load only when item is actually visible or very close to viewport
61
+ // Much more conservative - only load what's immediately needed
62
+ const isInView = rect.top < windowHeight && rect.bottom > 0;
63
+
64
+ if (isInView) {
65
+ setIsMapLoaded(true);
44
66
  }
45
- isFavorite = !isFavorite;
46
- handleSettingFavorites(updatedFavorites);
47
67
  };
68
+
69
+ // Check immediately
70
+ checkIfInView();
71
+
72
+ // Only check on scroll, not continuously
73
+ let scrollTimeout;
74
+ const handleScroll = () => {
75
+ clearTimeout(scrollTimeout);
76
+ scrollTimeout = setTimeout(checkIfInView, 300); // Much less frequent
77
+ };
78
+
79
+ window.addEventListener('scroll', handleScroll, { passive: true });
80
+
81
+ return () => {
82
+ window.removeEventListener('scroll', handleScroll);
83
+ clearTimeout(scrollTimeout);
84
+ };
85
+ }, [isMobile, showMap, isMapLoaded]);
86
+
87
+ const handleClick = () => {
88
+ if (onItemSelected) {
89
+ onItemSelected(item);
90
+ }
91
+ };
92
+ let isFavorite = favorites.includes(item.id);
93
+
94
+ const handleFavouriteClick = (event, item) => {
95
+ if(!includeFavorite)return;
96
+ event.stopPropagation();
97
+ let updatedFavorites;
98
+ if (isFavorite) {
99
+ updatedFavorites = favorites.filter(fav => fav !== item.id);
100
+ } else {
101
+ updatedFavorites = [...favorites, item.id];
102
+ }
103
+ isFavorite = !isFavorite;
104
+ handleSettingFavorites(updatedFavorites);
105
+ };
48
106
  return (
49
107
  <button
50
- ref={ref}
108
+ ref={(el) => {
109
+ // Forward the ref to the parent component
110
+ if (ref) {
111
+ if (typeof ref === 'function') {
112
+ ref(el);
113
+ } else {
114
+ ref.current = el;
115
+ }
116
+ }
117
+ // Also store our own ref for scroll detection
118
+ itemRef.current = el;
119
+ }}
51
120
  onClick={() => { handleClick(); }}
52
121
  className={`
53
122
  hc-group hc-relative hc-flex md:hc-flex-col hc-w-full hc-text-left hc-bg-clip-border hc-border hc-border-transparent hc-break-words hc-overflow-hidden hc-cursor-pointer hc-transition-colors hover:hc-bg-uiAccent/5 focus:hover:hc-bg-uiAccent/5
@@ -111,12 +180,16 @@ const ListItem = forwardRef(
111
180
  }
112
181
  </Grid>
113
182
  {/* MOBILE ONLY: This map section is visible on mobile and hidden on desktop (md:hc-hidden) */}
114
- {showMap && item.mapDetails && googleMapsApiKey && (
115
- <div onClick={() => { setMobileTab("mapTab"); handleClick(); }} className="md:hc-hidden hc-w-2/5 sm:hc-w-1/3 hc-p-1.5 hc-my-1 hc-bg-uiAccent/5 hc-border hc-border-uiAccent/10 hc-rounded-sm">
183
+ {showMap && item.mapDetails?.staticMapUrl && (
184
+ <div
185
+ onClick={() => { setMobileTab("mapTab"); handleClick(); }}
186
+ className="md:hc-hidden hc-w-2/5 sm:hc-w-1/3 hc-p-1.5 hc-my-1 hc-bg-uiAccent/5 hc-border hc-border-uiAccent/10 hc-rounded-sm"
187
+ >
116
188
  <img
117
- src={`https://maps.googleapis.com/maps/api/staticmap?scale=2&center=${item.mapDetails.latitude},${item.mapDetails.longitude}&zoom=10&size=240x180&maptype=roadmap&markers=color:0x${mapPinColor}%7Clabel:•%7C${item.mapDetails.latitude},${item.mapDetails.longitude}&key=${googleMapsApiKey}`}
118
- alt={`Map of location for ${item.fields?.position || item.fields?.title || 'job'}`}
189
+ src={item.mapDetails.staticMapUrl}
190
+ alt={`Map of location for ${item.fields.position}`}
119
191
  className="hc-w-full hc-h-full hc-object-cover"
192
+ loading="lazy"
120
193
  />
121
194
  </div>
122
195
  )}
@@ -137,4 +210,4 @@ export default React.memo(ListItem, (prevProps, nextProps) => {
137
210
  prevProps.bodyClassName === nextProps.bodyClassName &&
138
211
  prevProps.className === nextProps.className
139
212
  );
140
- });
213
+ });