@mapfirst.ai/react 0.0.6 → 0.0.7

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/EXAMPLES.md CHANGED
@@ -386,6 +386,314 @@ function RealTimeUpdates() {
386
386
  }
387
387
  ```
388
388
 
389
+ ## Search Hooks Examples
390
+
391
+ ### Using `usePropertiesSearch` for Location-Based Search
392
+
393
+ ```tsx
394
+ import React, { useState } from "react";
395
+ import {
396
+ useMapFirstCore,
397
+ useMapLibreAttachment,
398
+ usePropertiesSearch,
399
+ } from "@mapfirst/react";
400
+ import maplibregl from "maplibre-gl";
401
+
402
+ function LocationSearchExample() {
403
+ const [city, setCity] = useState("Paris");
404
+ const [country, setCountry] = useState("France");
405
+
406
+ const { mapFirst, state } = useMapFirstCore({
407
+ initialLocationData: { city, country, currency: "USD" },
408
+ });
409
+
410
+ const { search, isLoading, error } = usePropertiesSearch(mapFirst);
411
+
412
+ const handleSearch = async () => {
413
+ try {
414
+ await search({
415
+ body: {
416
+ city,
417
+ country,
418
+ filters: {
419
+ checkIn: new Date("2024-06-01"),
420
+ checkOut: new Date("2024-06-07"),
421
+ numAdults: 2,
422
+ numRooms: 1,
423
+ currency: "USD",
424
+ },
425
+ },
426
+ });
427
+ } catch (err) {
428
+ console.error("Search failed:", err);
429
+ }
430
+ };
431
+
432
+ return (
433
+ <div>
434
+ <div>
435
+ <input
436
+ value={city}
437
+ onChange={(e) => setCity(e.target.value)}
438
+ placeholder="City"
439
+ />
440
+ <input
441
+ value={country}
442
+ onChange={(e) => setCountry(e.target.value)}
443
+ placeholder="Country"
444
+ />
445
+ <button onClick={handleSearch} disabled={isLoading}>
446
+ {isLoading ? "Searching..." : "Search"}
447
+ </button>
448
+ </div>
449
+ {error && <div style={{ color: "red" }}>Error: {error.message}</div>}
450
+ <div>Found {state?.properties.length || 0} properties</div>
451
+ </div>
452
+ );
453
+ }
454
+ ```
455
+
456
+ ### Using `useSmartFilterSearch` for Natural Language Queries
457
+
458
+ ```tsx
459
+ import React, { useState } from "react";
460
+ import {
461
+ useMapFirstCore,
462
+ useMapLibreAttachment,
463
+ useSmartFilterSearch,
464
+ } from "@mapfirst/react";
465
+ import maplibregl from "maplibre-gl";
466
+
467
+ function SmartSearchExample() {
468
+ const [query, setQuery] = useState("");
469
+
470
+ const { mapFirst, state } = useMapFirstCore({
471
+ initialLocationData: {
472
+ city: "New York",
473
+ country: "United States",
474
+ currency: "USD",
475
+ },
476
+ });
477
+
478
+ const { search, isLoading, error } = useSmartFilterSearch(mapFirst);
479
+
480
+ const handleSearch = async (e: React.FormEvent) => {
481
+ e.preventDefault();
482
+ if (!query.trim()) return;
483
+
484
+ try {
485
+ await search({ query });
486
+ } catch (err) {
487
+ console.error("Search failed:", err);
488
+ }
489
+ };
490
+
491
+ const exampleQueries = [
492
+ "Hotels near Times Square with free wifi",
493
+ "4-star hotels with pool and gym",
494
+ "Budget hotels under $150",
495
+ "Luxury hotels with spa",
496
+ ];
497
+
498
+ return (
499
+ <div>
500
+ <form onSubmit={handleSearch}>
501
+ <input
502
+ type="text"
503
+ value={query}
504
+ onChange={(e) => setQuery(e.target.value)}
505
+ placeholder="Try: hotels near beach with pool"
506
+ style={{ width: "400px", padding: "8px" }}
507
+ />
508
+ <button type="submit" disabled={isLoading}>
509
+ {isLoading ? "Searching..." : "Search"}
510
+ </button>
511
+ </form>
512
+
513
+ <div style={{ marginTop: "10px" }}>
514
+ <strong>Try these examples:</strong>
515
+ <ul>
516
+ {exampleQueries.map((q) => (
517
+ <li key={q}>
518
+ <button
519
+ onClick={() => {
520
+ setQuery(q);
521
+ search({ query: q });
522
+ }}
523
+ disabled={isLoading}
524
+ style={{ textAlign: "left", padding: "4px 8px" }}
525
+ >
526
+ {q}
527
+ </button>
528
+ </li>
529
+ ))}
530
+ </ul>
531
+ </div>
532
+
533
+ {error && (
534
+ <div style={{ color: "red", marginTop: "10px" }}>
535
+ Error: {error.message}
536
+ </div>
537
+ )}
538
+
539
+ <div style={{ marginTop: "10px" }}>
540
+ {isLoading ? (
541
+ <p>Searching...</p>
542
+ ) : (
543
+ <p>Found {state?.properties.length || 0} properties</p>
544
+ )}
545
+ </div>
546
+ </div>
547
+ );
548
+ }
549
+ ```
550
+
551
+ ### Combined Search with Filters
552
+
553
+ ```tsx
554
+ import React, { useState } from "react";
555
+ import {
556
+ useMapFirstCore,
557
+ usePropertiesSearch,
558
+ useSmartFilterSearch,
559
+ } from "@mapfirst/react";
560
+
561
+ type SearchMode = "location" | "smart";
562
+
563
+ function CombinedSearchExample() {
564
+ const [mode, setMode] = useState<SearchMode>("location");
565
+ const [city, setCity] = useState("Los Angeles");
566
+ const [country, setCountry] = useState("United States");
567
+ const [query, setQuery] = useState("");
568
+
569
+ const { mapFirst, state } = useMapFirstCore({
570
+ initialLocationData: { city, country, currency: "USD" },
571
+ });
572
+
573
+ const propertiesSearch = usePropertiesSearch(mapFirst);
574
+ const smartSearch = useSmartFilterSearch(mapFirst);
575
+
576
+ const currentSearch = mode === "location" ? propertiesSearch : smartSearch;
577
+
578
+ const handleLocationSearch = async () => {
579
+ try {
580
+ await propertiesSearch.search({
581
+ body: {
582
+ city,
583
+ country,
584
+ filters: {
585
+ checkIn: new Date("2024-06-01"),
586
+ checkOut: new Date("2024-06-07"),
587
+ numAdults: 2,
588
+ numRooms: 1,
589
+ currency: "USD",
590
+ },
591
+ },
592
+ });
593
+ } catch (err) {
594
+ console.error("Location search failed:", err);
595
+ }
596
+ };
597
+
598
+ const handleSmartSearch = async () => {
599
+ if (!query.trim()) return;
600
+ try {
601
+ await smartSearch.search({ query });
602
+ } catch (err) {
603
+ console.error("Smart search failed:", err);
604
+ }
605
+ };
606
+
607
+ return (
608
+ <div>
609
+ <div>
610
+ <label>
611
+ <input
612
+ type="radio"
613
+ checked={mode === "location"}
614
+ onChange={() => setMode("location")}
615
+ />
616
+ Location Search
617
+ </label>
618
+ <label style={{ marginLeft: "20px" }}>
619
+ <input
620
+ type="radio"
621
+ checked={mode === "smart"}
622
+ onChange={() => setMode("smart")}
623
+ />
624
+ Smart Search
625
+ </label>
626
+ </div>
627
+
628
+ {mode === "location" ? (
629
+ <div style={{ marginTop: "10px" }}>
630
+ <input
631
+ value={city}
632
+ onChange={(e) => setCity(e.target.value)}
633
+ placeholder="City"
634
+ />
635
+ <input
636
+ value={country}
637
+ onChange={(e) => setCountry(e.target.value)}
638
+ placeholder="Country"
639
+ style={{ marginLeft: "10px" }}
640
+ />
641
+ <button
642
+ onClick={handleLocationSearch}
643
+ disabled={currentSearch.isLoading}
644
+ >
645
+ Search
646
+ </button>
647
+ </div>
648
+ ) : (
649
+ <div style={{ marginTop: "10px" }}>
650
+ <input
651
+ value={query}
652
+ onChange={(e) => setQuery(e.target.value)}
653
+ placeholder="Describe what you're looking for..."
654
+ style={{ width: "400px" }}
655
+ />
656
+ <button
657
+ onClick={handleSmartSearch}
658
+ disabled={currentSearch.isLoading}
659
+ >
660
+ Search
661
+ </button>
662
+ </div>
663
+ )}
664
+
665
+ {currentSearch.error && (
666
+ <div style={{ color: "red", marginTop: "10px" }}>
667
+ Error: {currentSearch.error.message}
668
+ </div>
669
+ )}
670
+
671
+ <div style={{ marginTop: "10px" }}>
672
+ {currentSearch.isLoading ? (
673
+ <p>Searching...</p>
674
+ ) : (
675
+ <p>Found {state?.properties.length || 0} properties</p>
676
+ )}
677
+ </div>
678
+
679
+ <div style={{ marginTop: "20px" }}>
680
+ <h3>Results:</h3>
681
+ <ul>
682
+ {state?.properties.slice(0, 5).map((property) => (
683
+ <li key={property.tripadvisor_id}>
684
+ <strong>{property.name}</strong>
685
+ {property.pricing && (
686
+ <span> - ${property.pricing.display_price}</span>
687
+ )}
688
+ </li>
689
+ ))}
690
+ </ul>
691
+ </div>
692
+ </div>
693
+ );
694
+ }
695
+ ```
696
+
389
697
  ## TypeScript Usage
390
698
 
391
699
  Full type safety with TypeScript:
package/README.md CHANGED
@@ -499,6 +499,119 @@ const selectedId = useMapFirstSelectedProperty(mapFirst);
499
499
  return <div>Selected: {selectedId || 'None'}</div>;
500
500
  ```
501
501
 
502
+ ### `usePropertiesSearch`
503
+
504
+ Hook to run properties search with the MapFirst SDK. Returns a function to trigger the search and loading state.
505
+
506
+ **Parameters:**
507
+
508
+ - `mapFirst` - SDK instance from `useMapFirstCore`
509
+
510
+ **Returns:** `{ search: Function, isLoading: boolean, error: Error | null }`
511
+
512
+ **Example:**
513
+
514
+ ```tsx
515
+ const { mapFirst } = useMapFirstCore({ ... });
516
+ const { search, isLoading, error } = usePropertiesSearch(mapFirst);
517
+
518
+ const handleSearch = async () => {
519
+ try {
520
+ await search({
521
+ body: {
522
+ city: "Paris",
523
+ country: "France",
524
+ filters: {
525
+ checkIn: new Date(),
526
+ checkOut: new Date(Date.now() + 86400000 * 3), // 3 days later
527
+ numAdults: 2,
528
+ numRooms: 1,
529
+ currency: "EUR"
530
+ }
531
+ }
532
+ });
533
+ } catch (err) {
534
+ console.error("Search failed:", err);
535
+ }
536
+ };
537
+
538
+ return (
539
+ <div>
540
+ <button onClick={handleSearch} disabled={isLoading}>
541
+ {isLoading ? "Searching..." : "Search Properties"}
542
+ </button>
543
+ {error && <p>Error: {error.message}</p>}
544
+ </div>
545
+ );
546
+ ```
547
+
548
+ ### `useSmartFilterSearch`
549
+
550
+ Hook to run smart filter search with natural language queries or predefined filters.
551
+
552
+ **Parameters:**
553
+
554
+ - `mapFirst` - SDK instance from `useMapFirstCore`
555
+
556
+ **Returns:** `{ search: Function, isLoading: boolean, error: Error | null }`
557
+
558
+ **Example with natural language query:**
559
+
560
+ ```tsx
561
+ const { mapFirst } = useMapFirstCore({ ... });
562
+ const { search, isLoading, error } = useSmartFilterSearch(mapFirst);
563
+
564
+ const handleSearch = async (query: string) => {
565
+ try {
566
+ await search({ query });
567
+ } catch (err) {
568
+ console.error("Search failed:", err);
569
+ }
570
+ };
571
+
572
+ return (
573
+ <div>
574
+ <input
575
+ type="text"
576
+ placeholder="e.g., hotels near beach with pool"
577
+ onKeyDown={(e) => {
578
+ if (e.key === 'Enter') {
579
+ handleSearch(e.currentTarget.value);
580
+ }
581
+ }}
582
+ />
583
+ {isLoading && <p>Searching...</p>}
584
+ {error && <p>Error: {error.message}</p>}
585
+ </div>
586
+ );
587
+ ```
588
+
589
+ **Example with predefined filters:**
590
+
591
+ ```tsx
592
+ const { mapFirst } = useMapFirstCore({ ... });
593
+ const { search, isLoading, error } = useSmartFilterSearch(mapFirst);
594
+
595
+ const handleFilterSearch = async () => {
596
+ try {
597
+ await search({
598
+ filters: [
599
+ { id: "pool", label: "Pool", type: "amenity", value: "pool" },
600
+ { id: "4star", label: "4 Star", type: "starRating", value: "4", numericValue: 4 }
601
+ ]
602
+ });
603
+ } catch (err) {
604
+ console.error("Search failed:", err);
605
+ }
606
+ };
607
+
608
+ return (
609
+ <button onClick={handleFilterSearch} disabled={isLoading}>
610
+ Apply Filters
611
+ </button>
612
+ );
613
+ ```
614
+
502
615
  ## Legacy API
503
616
 
504
617
  The old `useMapFirst` hook is still available but deprecated:
package/dist/index.d.mts CHANGED
@@ -2,6 +2,40 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { BaseMapFirstOptions, MapFirstCore, MapState, Property, PropertyType, MapLibreNamespace, GoogleMapsNamespace, MapboxNamespace, MapFirstOptions } from '@mapfirst.ai/core';
4
4
 
5
+ type InitialRequestBody = {
6
+ initial?: boolean;
7
+ query?: string;
8
+ bounds?: {
9
+ sw: {
10
+ lat: number;
11
+ lng: number;
12
+ };
13
+ ne: {
14
+ lat: number;
15
+ lng: number;
16
+ };
17
+ };
18
+ filters?: any;
19
+ city?: string;
20
+ country?: string;
21
+ location_id?: number;
22
+ longitude?: number;
23
+ latitude?: number;
24
+ radius?: number;
25
+ };
26
+ type SmartFilter = {
27
+ id: string;
28
+ label: string;
29
+ type: "amenity" | "hotelStyle" | "priceRange" | "minRating" | "starRating" | "primary_type" | "transformed_query" | "selected_restaurant_price_levels";
30
+ value: string;
31
+ numericValue?: number;
32
+ priceRange?: {
33
+ min: number;
34
+ max?: number;
35
+ };
36
+ propertyType?: PropertyType;
37
+ priceLevels?: any[];
38
+ };
5
39
  /**
6
40
  * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.
7
41
  * Supports two-phase initialization: create SDK first, attach map later.
@@ -188,6 +222,151 @@ declare function useMapboxAttachment({ mapFirst, map, mapboxgl, onMarkerClick, }
188
222
  * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead
189
223
  */
190
224
  declare function useMapFirst(options: MapFirstOptions | null): React.RefObject<MapFirstCore | null>;
225
+ /**
226
+ * Hook to run properties search with the MapFirst SDK.
227
+ * Returns a function to trigger the search and loading state.
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * const { mapFirst } = useMapFirstCore({ ... });
232
+ * const { search, isLoading, error } = usePropertiesSearch(mapFirst);
233
+ *
234
+ * const handleSearch = async () => {
235
+ * await search({
236
+ * body: {
237
+ * city: "Paris",
238
+ * country: "France",
239
+ * filters: {
240
+ * checkIn: new Date(),
241
+ * checkOut: new Date(Date.now() + 86400000),
242
+ * numAdults: 2,
243
+ * numRooms: 1
244
+ * }
245
+ * }
246
+ * });
247
+ * };
248
+ * ```
249
+ */
250
+ declare function usePropertiesSearch(mapFirst: MapFirstCore | null): {
251
+ search: (options: {
252
+ body: InitialRequestBody;
253
+ beforeApplyProperties?: (data: any) => {
254
+ price?: any;
255
+ limit?: number;
256
+ };
257
+ smartFiltersClearable?: boolean;
258
+ }) => Promise<{
259
+ location_id?: number;
260
+ filters: {
261
+ amenities?: string[];
262
+ hotelStyle?: string[];
263
+ price?: {
264
+ min: number;
265
+ max: number;
266
+ } | null;
267
+ minRating?: number;
268
+ starRating?: number;
269
+ numAdults: number;
270
+ numRooms: number;
271
+ checkIn: string;
272
+ checkOut: string;
273
+ location?: {
274
+ locationId: number | null;
275
+ city: string | null;
276
+ state: string | null;
277
+ country: string | null;
278
+ longitude: number | null;
279
+ latitude: number | null;
280
+ } | null;
281
+ currency: string;
282
+ limit?: number;
283
+ language?: "en" | "es" | "de" | "fr" | "it" | "pt";
284
+ primary_type?: PropertyType;
285
+ transformed_query?: string;
286
+ selected_restaurant_price_levels?: ("Mid Range" | "Fine Dining" | "Cheap Eats")[];
287
+ };
288
+ properties: Property[];
289
+ isComplete: boolean | undefined;
290
+ pollingLink: string | undefined;
291
+ durationSeconds: number;
292
+ } | null>;
293
+ isLoading: boolean;
294
+ error: Error | null;
295
+ };
296
+ /**
297
+ * Hook to run smart filter search with the MapFirst SDK.
298
+ * Returns a function to trigger the search and loading state.
299
+ *
300
+ * @example
301
+ * ```tsx
302
+ * const { mapFirst } = useMapFirstCore({ ... });
303
+ * const { search, isLoading, error } = useSmartFilterSearch(mapFirst);
304
+ *
305
+ * const handleSearch = async () => {
306
+ * await search({
307
+ * query: "hotels near beach with pool"
308
+ * });
309
+ * };
310
+ *
311
+ * // Or with filters
312
+ * const handleFilterSearch = async () => {
313
+ * await search({
314
+ * filters: [
315
+ * { id: "pool", label: "Pool", type: "amenity", value: "pool" },
316
+ * { id: "4star", label: "4 Star", type: "starRating", value: "4", numericValue: 4 }
317
+ * ]
318
+ * });
319
+ * };
320
+ * ```
321
+ */
322
+ declare function useSmartFilterSearch(mapFirst: MapFirstCore | null): {
323
+ search: (options: {
324
+ query?: string;
325
+ filters?: SmartFilter[];
326
+ onProcessFilters?: (filters: any, location_id?: number) => {
327
+ smartFilters?: SmartFilter[];
328
+ price?: any;
329
+ limit?: number;
330
+ language?: string;
331
+ };
332
+ }) => Promise<{
333
+ location_id?: number;
334
+ filters: {
335
+ amenities?: string[];
336
+ hotelStyle?: string[];
337
+ price?: {
338
+ min: number;
339
+ max: number;
340
+ } | null;
341
+ minRating?: number;
342
+ starRating?: number;
343
+ numAdults: number;
344
+ numRooms: number;
345
+ checkIn: string;
346
+ checkOut: string;
347
+ location?: {
348
+ locationId: number | null;
349
+ city: string | null;
350
+ state: string | null;
351
+ country: string | null;
352
+ longitude: number | null;
353
+ latitude: number | null;
354
+ } | null;
355
+ currency: string;
356
+ limit?: number;
357
+ language?: "en" | "es" | "de" | "fr" | "it" | "pt";
358
+ primary_type?: PropertyType;
359
+ transformed_query?: string;
360
+ selected_restaurant_price_levels?: ("Mid Range" | "Fine Dining" | "Cheap Eats")[];
361
+ };
362
+ properties: Property[];
363
+ isComplete: boolean | undefined;
364
+ pollingLink: string | undefined;
365
+ durationSeconds: number;
366
+ } | null>;
367
+ isLoading: boolean;
368
+ error: Error | null;
369
+ };
191
370
  /**
192
371
  * Helper component that simply renders the markers it receives so non-React environments
193
372
  * can verify data flows before wiring the SDK into a map.
@@ -196,4 +375,4 @@ declare function MarkerDebugList({ markers }: {
196
375
  markers: Property[];
197
376
  }): react_jsx_runtime.JSX.Element;
198
377
 
199
- export { MarkerDebugList, useGoogleMapsAttachment, useMapFirst, useMapFirstCore, useMapFirstProperties, useMapFirstSelectedProperty, useMapLibreAttachment, useMapboxAttachment, usePrimaryType, useSelectedMarker };
378
+ export { MarkerDebugList, useGoogleMapsAttachment, useMapFirst, useMapFirstCore, useMapFirstProperties, useMapFirstSelectedProperty, useMapLibreAttachment, useMapboxAttachment, usePrimaryType, usePropertiesSearch, useSelectedMarker, useSmartFilterSearch };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,40 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { BaseMapFirstOptions, MapFirstCore, MapState, Property, PropertyType, MapLibreNamespace, GoogleMapsNamespace, MapboxNamespace, MapFirstOptions } from '@mapfirst.ai/core';
4
4
 
5
+ type InitialRequestBody = {
6
+ initial?: boolean;
7
+ query?: string;
8
+ bounds?: {
9
+ sw: {
10
+ lat: number;
11
+ lng: number;
12
+ };
13
+ ne: {
14
+ lat: number;
15
+ lng: number;
16
+ };
17
+ };
18
+ filters?: any;
19
+ city?: string;
20
+ country?: string;
21
+ location_id?: number;
22
+ longitude?: number;
23
+ latitude?: number;
24
+ radius?: number;
25
+ };
26
+ type SmartFilter = {
27
+ id: string;
28
+ label: string;
29
+ type: "amenity" | "hotelStyle" | "priceRange" | "minRating" | "starRating" | "primary_type" | "transformed_query" | "selected_restaurant_price_levels";
30
+ value: string;
31
+ numericValue?: number;
32
+ priceRange?: {
33
+ min: number;
34
+ max?: number;
35
+ };
36
+ propertyType?: PropertyType;
37
+ priceLevels?: any[];
38
+ };
5
39
  /**
6
40
  * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.
7
41
  * Supports two-phase initialization: create SDK first, attach map later.
@@ -188,6 +222,151 @@ declare function useMapboxAttachment({ mapFirst, map, mapboxgl, onMarkerClick, }
188
222
  * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead
189
223
  */
190
224
  declare function useMapFirst(options: MapFirstOptions | null): React.RefObject<MapFirstCore | null>;
225
+ /**
226
+ * Hook to run properties search with the MapFirst SDK.
227
+ * Returns a function to trigger the search and loading state.
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * const { mapFirst } = useMapFirstCore({ ... });
232
+ * const { search, isLoading, error } = usePropertiesSearch(mapFirst);
233
+ *
234
+ * const handleSearch = async () => {
235
+ * await search({
236
+ * body: {
237
+ * city: "Paris",
238
+ * country: "France",
239
+ * filters: {
240
+ * checkIn: new Date(),
241
+ * checkOut: new Date(Date.now() + 86400000),
242
+ * numAdults: 2,
243
+ * numRooms: 1
244
+ * }
245
+ * }
246
+ * });
247
+ * };
248
+ * ```
249
+ */
250
+ declare function usePropertiesSearch(mapFirst: MapFirstCore | null): {
251
+ search: (options: {
252
+ body: InitialRequestBody;
253
+ beforeApplyProperties?: (data: any) => {
254
+ price?: any;
255
+ limit?: number;
256
+ };
257
+ smartFiltersClearable?: boolean;
258
+ }) => Promise<{
259
+ location_id?: number;
260
+ filters: {
261
+ amenities?: string[];
262
+ hotelStyle?: string[];
263
+ price?: {
264
+ min: number;
265
+ max: number;
266
+ } | null;
267
+ minRating?: number;
268
+ starRating?: number;
269
+ numAdults: number;
270
+ numRooms: number;
271
+ checkIn: string;
272
+ checkOut: string;
273
+ location?: {
274
+ locationId: number | null;
275
+ city: string | null;
276
+ state: string | null;
277
+ country: string | null;
278
+ longitude: number | null;
279
+ latitude: number | null;
280
+ } | null;
281
+ currency: string;
282
+ limit?: number;
283
+ language?: "en" | "es" | "de" | "fr" | "it" | "pt";
284
+ primary_type?: PropertyType;
285
+ transformed_query?: string;
286
+ selected_restaurant_price_levels?: ("Mid Range" | "Fine Dining" | "Cheap Eats")[];
287
+ };
288
+ properties: Property[];
289
+ isComplete: boolean | undefined;
290
+ pollingLink: string | undefined;
291
+ durationSeconds: number;
292
+ } | null>;
293
+ isLoading: boolean;
294
+ error: Error | null;
295
+ };
296
+ /**
297
+ * Hook to run smart filter search with the MapFirst SDK.
298
+ * Returns a function to trigger the search and loading state.
299
+ *
300
+ * @example
301
+ * ```tsx
302
+ * const { mapFirst } = useMapFirstCore({ ... });
303
+ * const { search, isLoading, error } = useSmartFilterSearch(mapFirst);
304
+ *
305
+ * const handleSearch = async () => {
306
+ * await search({
307
+ * query: "hotels near beach with pool"
308
+ * });
309
+ * };
310
+ *
311
+ * // Or with filters
312
+ * const handleFilterSearch = async () => {
313
+ * await search({
314
+ * filters: [
315
+ * { id: "pool", label: "Pool", type: "amenity", value: "pool" },
316
+ * { id: "4star", label: "4 Star", type: "starRating", value: "4", numericValue: 4 }
317
+ * ]
318
+ * });
319
+ * };
320
+ * ```
321
+ */
322
+ declare function useSmartFilterSearch(mapFirst: MapFirstCore | null): {
323
+ search: (options: {
324
+ query?: string;
325
+ filters?: SmartFilter[];
326
+ onProcessFilters?: (filters: any, location_id?: number) => {
327
+ smartFilters?: SmartFilter[];
328
+ price?: any;
329
+ limit?: number;
330
+ language?: string;
331
+ };
332
+ }) => Promise<{
333
+ location_id?: number;
334
+ filters: {
335
+ amenities?: string[];
336
+ hotelStyle?: string[];
337
+ price?: {
338
+ min: number;
339
+ max: number;
340
+ } | null;
341
+ minRating?: number;
342
+ starRating?: number;
343
+ numAdults: number;
344
+ numRooms: number;
345
+ checkIn: string;
346
+ checkOut: string;
347
+ location?: {
348
+ locationId: number | null;
349
+ city: string | null;
350
+ state: string | null;
351
+ country: string | null;
352
+ longitude: number | null;
353
+ latitude: number | null;
354
+ } | null;
355
+ currency: string;
356
+ limit?: number;
357
+ language?: "en" | "es" | "de" | "fr" | "it" | "pt";
358
+ primary_type?: PropertyType;
359
+ transformed_query?: string;
360
+ selected_restaurant_price_levels?: ("Mid Range" | "Fine Dining" | "Cheap Eats")[];
361
+ };
362
+ properties: Property[];
363
+ isComplete: boolean | undefined;
364
+ pollingLink: string | undefined;
365
+ durationSeconds: number;
366
+ } | null>;
367
+ isLoading: boolean;
368
+ error: Error | null;
369
+ };
191
370
  /**
192
371
  * Helper component that simply renders the markers it receives so non-React environments
193
372
  * can verify data flows before wiring the SDK into a map.
@@ -196,4 +375,4 @@ declare function MarkerDebugList({ markers }: {
196
375
  markers: Property[];
197
376
  }): react_jsx_runtime.JSX.Element;
198
377
 
199
- export { MarkerDebugList, useGoogleMapsAttachment, useMapFirst, useMapFirstCore, useMapFirstProperties, useMapFirstSelectedProperty, useMapLibreAttachment, useMapboxAttachment, usePrimaryType, useSelectedMarker };
378
+ export { MarkerDebugList, useGoogleMapsAttachment, useMapFirst, useMapFirstCore, useMapFirstProperties, useMapFirstSelectedProperty, useMapLibreAttachment, useMapboxAttachment, usePrimaryType, usePropertiesSearch, useSelectedMarker, useSmartFilterSearch };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var S=Object.create;var d=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var m=(e,n)=>{for(var r in n)d(e,r,{get:n[r],enumerable:!0})},C=(e,n,r,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of b(n))!k.call(e,a)&&a!==r&&d(e,a,{get:()=>n[a],enumerable:!(o=h(n,a))||o.enumerable});return e};var x=(e,n,r)=>(r=e!=null?S(P(e)):{},C(n||!e||!e.__esModule?d(r,"default",{value:e,enumerable:!0}):r,e)),R=e=>C(d({},"__esModule",{value:!0}),e);var w={};m(w,{MarkerDebugList:()=>G,useGoogleMapsAttachment:()=>O,useMapFirst:()=>B,useMapFirstCore:()=>T,useMapFirstProperties:()=>E,useMapFirstSelectedProperty:()=>L,useMapLibreAttachment:()=>N,useMapboxAttachment:()=>I,usePrimaryType:()=>F,useSelectedMarker:()=>A});module.exports=R(w);var s=x(require("react")),M=require("@mapfirst.ai/core"),p=require("react/jsx-runtime");function T(e){let n=s.default.useRef(null),[r,o]=s.default.useState(null),a=s.default.useRef(e);return s.default.useEffect(()=>{a.current=e}),s.default.useEffect(()=>{let f=a.current,y={adapter:null,...f,callbacks:{...f.callbacks,onPropertiesChange:u=>{var t,l;o(c=>c?{...c,properties:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onPropertiesChange)==null||l.call(t,u)},onSelectedPropertyChange:u=>{var t,l;o(c=>c?{...c,selectedPropertyId:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onSelectedPropertyChange)==null||l.call(t,u)},onPrimaryTypeChange:u=>{var t,l;o(c=>c?{...c,primary:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onPrimaryTypeChange)==null||l.call(t,u)},onFiltersChange:u=>{var t,l;o(c=>c?{...c,filters:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onFiltersChange)==null||l.call(t,u)},onBoundsChange:u=>{var t,l;o(c=>c?{...c,bounds:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onBoundsChange)==null||l.call(t,u)},onCenterChange:(u,t)=>{var l,c;o(g=>g?{...g,center:u,zoom:t}:null),(c=(l=a.current.callbacks)==null?void 0:l.onCenterChange)==null||c.call(l,u,t)},onZoomChange:u=>{var t,l;o(c=>c?{...c,zoom:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onZoomChange)==null||l.call(t,u)},onActiveLocationChange:u=>{var t,l;o(c=>c?{...c,activeLocation:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onActiveLocationChange)==null||l.call(t,u)},onLoadingStateChange:u=>{var t,l;o(c=>c?{...c,initialLoading:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onLoadingStateChange)==null||l.call(t,u)},onSearchingStateChange:u=>{var t,l;o(c=>c?{...c,isSearching:u}:null),(l=(t=a.current.callbacks)==null?void 0:t.onSearchingStateChange)==null||l.call(t,u)}}},i=new M.MapFirstCore(y);return n.current=i,o(i.getState()),()=>{i.destroy(),n.current=null,o(null)}},[]),{mapFirst:n.current,state:r}}function E(e){let[n,r]=s.default.useState([]);return s.default.useEffect(()=>{if(!e){r([]);return}r(e.getState().properties)},[e]),n}function L(e){let[n,r]=s.default.useState(null);return s.default.useEffect(()=>{if(!e){r(null);return}r(e.getState().selectedPropertyId)},[e]),n}function F(e){let[n,r]=s.default.useState("Accommodation");s.default.useEffect(()=>{if(!e){r("Accommodation");return}r(e.getState().primary)},[e]);let o=s.default.useCallback(a=>{e&&(e.setPrimaryType(a),r(a))},[e]);return[n,o]}function A(e){let[n,r]=s.default.useState(null);s.default.useEffect(()=>{if(!e){r(null);return}r(e.getState().selectedPropertyId)},[e]);let o=s.default.useCallback(a=>{e&&e.setSelectedMarker(a)},[e]);return[n,o]}function N({mapFirst:e,map:n,maplibregl:r,onMarkerClick:o}){let a=s.default.useRef(!1);s.default.useEffect(()=>{!e||!n||a.current||(e.attachMap(n,{platform:"maplibre",maplibregl:r,onMarkerClick:o}),a.current=!0)},[e,n,r,o])}function O({mapFirst:e,map:n,google:r,onMarkerClick:o}){let a=s.default.useRef(!1);s.default.useEffect(()=>{!e||!n||a.current||(e.attachMap(n,{platform:"google",google:r,onMarkerClick:o}),a.current=!0)},[e,n,r,o])}function I({mapFirst:e,map:n,mapboxgl:r,onMarkerClick:o}){let a=s.default.useRef(!1);s.default.useEffect(()=>{!e||!n||a.current||(e.attachMap(n,{platform:"mapbox",mapboxgl:r,onMarkerClick:o}),a.current=!0)},[e,n,r,o])}function B(e){let n=s.default.useRef(null);return s.default.useEffect(()=>{if(!e)return;let r=new M.MapFirstCore(e);return n.current=r,()=>{r.destroy(),n.current=null}},[e]),n}function G({markers:e}){return(0,p.jsxs)("div",{style:{fontFamily:"sans-serif",fontSize:14},children:[(0,p.jsx)("strong",{children:"Markers"}),(0,p.jsx)("ul",{children:e.map(n=>{var r,o,a,f,y,i;return(0,p.jsxs)("li",{children:[n.name," \u2014 ",(a=(o=(r=n.location)==null?void 0:r.lat)==null?void 0:o.toFixed(3))!=null?a:"n/a",","," ",(i=(y=(f=n.location)==null?void 0:f.lon)==null?void 0:y.toFixed(3))!=null?i:"n/a"]},String(n.tripadvisor_id))})})]})}0&&(module.exports={MarkerDebugList,useGoogleMapsAttachment,useMapFirst,useMapFirstCore,useMapFirstProperties,useMapFirstSelectedProperty,useMapLibreAttachment,useMapboxAttachment,usePrimaryType,useSelectedMarker});
1
+ "use strict";var m=Object.create;var g=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var C=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var E=(e,t)=>{for(var a in t)g(e,a,{get:t[a],enumerable:!0})},S=(e,t,a,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of M(t))!P.call(e,n)&&n!==a&&g(e,n,{get:()=>t[n],enumerable:!(l=h(t,n))||l.enumerable});return e};var k=(e,t,a)=>(a=e!=null?m(C(e)):{},S(t||!e||!e.__esModule?g(a,"default",{value:e,enumerable:!0}):a,e)),R=e=>S(g({},"__esModule",{value:!0}),e);var q={};E(q,{MarkerDebugList:()=>O,useGoogleMapsAttachment:()=>A,useMapFirst:()=>v,useMapFirstCore:()=>x,useMapFirstProperties:()=>F,useMapFirstSelectedProperty:()=>w,useMapLibreAttachment:()=>I,useMapboxAttachment:()=>_,usePrimaryType:()=>L,usePropertiesSearch:()=>B,useSelectedMarker:()=>T,useSmartFilterSearch:()=>N});module.exports=R(q);var u=k(require("react")),d=require("@mapfirst.ai/core"),f=require("react/jsx-runtime");function x(e){let t=u.default.useRef(null),[a,l]=u.default.useState(null),n=u.default.useRef(e);return u.default.useEffect(()=>{n.current=e}),u.default.useEffect(()=>{let y=n.current,p={adapter:null,...y,callbacks:{...y.callbacks,onPropertiesChange:o=>{var r,s;l(c=>c?{...c,properties:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onPropertiesChange)==null||s.call(r,o)},onSelectedPropertyChange:o=>{var r,s;l(c=>c?{...c,selectedPropertyId:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onSelectedPropertyChange)==null||s.call(r,o)},onPrimaryTypeChange:o=>{var r,s;l(c=>c?{...c,primary:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onPrimaryTypeChange)==null||s.call(r,o)},onFiltersChange:o=>{var r,s;l(c=>c?{...c,filters:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onFiltersChange)==null||s.call(r,o)},onBoundsChange:o=>{var r,s;l(c=>c?{...c,bounds:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onBoundsChange)==null||s.call(r,o)},onCenterChange:(o,r)=>{var s,c;l(b=>b?{...b,center:o,zoom:r}:null),(c=(s=n.current.callbacks)==null?void 0:s.onCenterChange)==null||c.call(s,o,r)},onZoomChange:o=>{var r,s;l(c=>c?{...c,zoom:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onZoomChange)==null||s.call(r,o)},onActiveLocationChange:o=>{var r,s;l(c=>c?{...c,activeLocation:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onActiveLocationChange)==null||s.call(r,o)},onLoadingStateChange:o=>{var r,s;l(c=>c?{...c,initialLoading:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onLoadingStateChange)==null||s.call(r,o)},onSearchingStateChange:o=>{var r,s;l(c=>c?{...c,isSearching:o}:null),(s=(r=n.current.callbacks)==null?void 0:r.onSearchingStateChange)==null||s.call(r,o)}}},i=new d.MapFirstCore(p);return t.current=i,l(i.getState()),()=>{i.destroy(),t.current=null,l(null)}},[]),{mapFirst:t.current,state:a}}function F(e){let[t,a]=u.default.useState([]);return u.default.useEffect(()=>{if(!e){a([]);return}a(e.getState().properties)},[e]),t}function w(e){let[t,a]=u.default.useState(null);return u.default.useEffect(()=>{if(!e){a(null);return}a(e.getState().selectedPropertyId)},[e]),t}function L(e){let[t,a]=u.default.useState("Accommodation");u.default.useEffect(()=>{if(!e){a("Accommodation");return}a(e.getState().primary)},[e]);let l=u.default.useCallback(n=>{e&&(e.setPrimaryType(n),a(n))},[e]);return[t,l]}function T(e){let[t,a]=u.default.useState(null);u.default.useEffect(()=>{if(!e){a(null);return}a(e.getState().selectedPropertyId)},[e]);let l=u.default.useCallback(n=>{e&&e.setSelectedMarker(n)},[e]);return[t,l]}function I({mapFirst:e,map:t,maplibregl:a,onMarkerClick:l}){let n=u.default.useRef(!1);u.default.useEffect(()=>{!e||!t||n.current||(e.attachMap(t,{platform:"maplibre",maplibregl:a,onMarkerClick:l}),n.current=!0)},[e,t,a,l])}function A({mapFirst:e,map:t,google:a,onMarkerClick:l}){let n=u.default.useRef(!1);u.default.useEffect(()=>{!e||!t||n.current||(e.attachMap(t,{platform:"google",google:a,onMarkerClick:l}),n.current=!0)},[e,t,a,l])}function _({mapFirst:e,map:t,mapboxgl:a,onMarkerClick:l}){let n=u.default.useRef(!1);u.default.useEffect(()=>{!e||!t||n.current||(e.attachMap(t,{platform:"mapbox",mapboxgl:a,onMarkerClick:l}),n.current=!0)},[e,t,a,l])}function v(e){let t=u.default.useRef(null);return u.default.useEffect(()=>{if(!e)return;let a=new d.MapFirstCore(e);return t.current=a,()=>{a.destroy(),t.current=null}},[e]),t}function B(e){let[t,a]=u.default.useState(!1),[l,n]=u.default.useState(null);return{search:u.default.useCallback(async p=>{if(!e){let i=new Error("MapFirst instance not available");throw n(i),i}a(!0),n(null);try{return await e.runPropertiesSearch({...p,onError:o=>{let r=o instanceof Error?o:new Error(String(o));n(r)}})}catch(i){let o=i instanceof Error?i:new Error(String(i));throw n(o),o}finally{a(!1)}},[e]),isLoading:t,error:l}}function N(e){let[t,a]=u.default.useState(!1),[l,n]=u.default.useState(null);return{search:u.default.useCallback(async p=>{if(!e){let i=new Error("MapFirst instance not available");throw n(i),i}a(!0),n(null);try{return await e.runSmartFilterSearch({...p,onError:o=>{let r=o instanceof Error?o:new Error(String(o));n(r)}})}catch(i){let o=i instanceof Error?i:new Error(String(i));throw n(o),o}finally{a(!1)}},[e]),isLoading:t,error:l}}function O({markers:e}){return(0,f.jsxs)("div",{style:{fontFamily:"sans-serif",fontSize:14},children:[(0,f.jsx)("strong",{children:"Markers"}),(0,f.jsx)("ul",{children:e.map(t=>{var a,l,n,y,p,i;return(0,f.jsxs)("li",{children:[t.name," \u2014 ",(n=(l=(a=t.location)==null?void 0:a.lat)==null?void 0:l.toFixed(3))!=null?n:"n/a",","," ",(i=(p=(y=t.location)==null?void 0:y.lon)==null?void 0:p.toFixed(3))!=null?i:"n/a"]},String(t.tripadvisor_id))})})]})}0&&(module.exports={MarkerDebugList,useGoogleMapsAttachment,useMapFirst,useMapFirstCore,useMapFirstProperties,useMapFirstSelectedProperty,useMapLibreAttachment,useMapboxAttachment,usePrimaryType,usePropertiesSearch,useSelectedMarker,useSmartFilterSearch});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n/**\n * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.\n * Supports two-phase initialization: create SDK first, attach map later.\n * Returns the instance and reactive state that updates when SDK state changes.\n *\n * @example\n * ```tsx\n * // Phase 1: Create SDK instance with location data\n * const { mapFirst, state } = useMapFirstCore({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state.properties); // Updates when properties change\n * console.log(state.isSearching); // Updates when search state changes\n *\n * // Phase 2: Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance && mapFirst) {\n * mapFirst.attachMap(mapLibreInstance, {\n * platform: \"maplibre\",\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance, mapFirst]);\n * ```\n */\nexport function useMapFirstCore(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { mapFirst: instanceRef.current, state };\n}\n\n/**\n * Hook to access reactive properties from MapFirst SDK.\n * Returns the current properties array that updates when properties change.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const properties = useMapFirstProperties(mapFirst);\n *\n * return <div>Found {properties.length} properties</div>;\n * ```\n */\nexport function useMapFirstProperties(\n mapFirst: MapFirstCore | null\n): Property[] {\n const [properties, setProperties] = React.useState<Property[]>([]);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setProperties([]);\n return;\n }\n\n // Initialize with current state\n setProperties(mapFirst.getState().properties);\n }, [mapFirst]);\n\n return properties;\n}\n\n/**\n * Hook to access the selected property ID from MapFirst SDK.\n * Returns the currently selected property ID that updates when selection changes.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const selectedId = useMapFirstSelectedProperty(mapFirst);\n *\n * return <div>Selected: {selectedId || 'None'}</div>;\n * ```\n */\nexport function useMapFirstSelectedProperty(\n mapFirst: MapFirstCore | null\n): number | null {\n const [selectedId, setSelectedId] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedId(null);\n return;\n }\n\n // Initialize with current state\n setSelectedId(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n return selectedId;\n}\n\n/**\n * Hook to access and control the primary property type.\n * Returns the current primary type and a setter function.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [primaryType, setPrimaryType] = usePrimaryType(mapFirst);\n *\n * return (\n * <select value={primaryType} onChange={(e) => setPrimaryType(e.target.value as PropertyType)}>\n * <option value=\"Accommodation\">Hotels</option>\n * <option value=\"Restaurant\">Restaurants</option>\n * <option value=\"Attraction\">Attractions</option>\n * </select>\n * );\n * ```\n */\nexport function usePrimaryType(\n mapFirst: MapFirstCore | null\n): [PropertyType, (type: PropertyType) => void] {\n const [primaryType, setPrimaryTypeState] =\n React.useState<PropertyType>(\"Accommodation\");\n\n React.useEffect(() => {\n if (!mapFirst) {\n setPrimaryTypeState(\"Accommodation\");\n return;\n }\n\n // Initialize with current state\n setPrimaryTypeState(mapFirst.getState().primary);\n }, [mapFirst]);\n\n const setPrimaryType = React.useCallback(\n (type: PropertyType) => {\n if (mapFirst) {\n mapFirst.setPrimaryType(type);\n setPrimaryTypeState(type);\n }\n },\n [mapFirst]\n );\n\n return [primaryType, setPrimaryType];\n}\n\n/**\n * Hook to access and control the selected marker.\n * Returns the current selected marker ID and a setter function.\n * Note: This hook requires the MapFirstCore instance. For simpler usage with reactive updates,\n * use state.selectedPropertyId from useMapFirstCore instead.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [selectedMarker, setSelectedMarker] = useSelectedMarker(mapFirst);\n *\n * return (\n * <div>\n * <p>Selected: {selectedMarker || 'None'}</p>\n * <button onClick={() => setSelectedMarker(null)}>Clear Selection</button>\n * </div>\n * );\n * ```\n */\nexport function useSelectedMarker(\n mapFirst: MapFirstCore | null\n): [number | null, (id: number | null) => void] {\n const [selectedMarker, setSelectedMarkerState] = React.useState<\n number | null\n >(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedMarkerState(null);\n return;\n }\n\n // Initialize with current state\n setSelectedMarkerState(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n const setSelectedMarker = React.useCallback(\n (id: number | null) => {\n if (mapFirst) {\n mapFirst.setSelectedMarker(id);\n }\n },\n [mapFirst]\n );\n\n return [selectedMarker, setSelectedMarker];\n}\n\n/**\n * Hook for MapLibre GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Paris\", country: \"France\" } });\n * const mapRef = useRef<maplibregl.Map | null>(null);\n *\n * useMapLibreAttachment({\n * mapFirst,\n * map: mapRef.current,\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * ```\n */\nexport function useMapLibreAttachment({\n mapFirst,\n map,\n maplibregl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n maplibregl: MapLibreNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, maplibregl, onMarkerClick]);\n}\n\n/**\n * Hook for Google Maps integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Tokyo\", country: \"Japan\" } });\n * const mapRef = useRef<google.maps.Map | null>(null);\n *\n * useGoogleMapsAttachment({\n * mapFirst,\n * map: mapRef.current,\n * google: window.google,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.isSearching);\n * ```\n */\nexport function useGoogleMapsAttachment({\n mapFirst,\n map,\n google,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n google: GoogleMapsNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, google, onMarkerClick]);\n}\n\n/**\n * Hook for Mapbox GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"London\", country: \"United Kingdom\" } });\n * const mapRef = useRef<mapboxgl.Map | null>(null);\n *\n * useMapboxAttachment({\n * mapFirst,\n * map: mapRef.current,\n * mapboxgl: mapboxgl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.filters);\n * ```\n */\nexport function useMapboxAttachment({\n mapFirst,\n map,\n mapboxgl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n mapboxgl: MapboxNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, mapboxgl, onMarkerClick]);\n}\n\n/**\n * Legacy hook that creates the MapFirstCore instance with a map immediately.\n * Use useMapFirstCore + useMap*Attachment hooks for better control.\n *\n * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead\n */\nexport function useMapFirst(options: MapFirstOptions | null) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n\n React.useEffect(() => {\n if (!options) {\n return undefined;\n }\n const instance = new MapFirstCore(options);\n instanceRef.current = instance;\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n };\n }, [options]);\n\n return instanceRef;\n}\n\n/**\n * Helper component that simply renders the markers it receives so non-React environments\n * can verify data flows before wiring the SDK into a map.\n */\nexport function MarkerDebugList({ markers }: { markers: Property[] }) {\n return (\n <div style={{ fontFamily: \"sans-serif\", fontSize: 14 }}>\n <strong>Markers</strong>\n <ul>\n {markers.map((marker) => (\n <li key={String(marker.tripadvisor_id)}>\n {marker.name} — {marker.location?.lat?.toFixed(3) ?? \"n/a\"},{\" \"}\n {marker.location?.lon?.toFixed(3) ?? \"n/a\"}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":"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","names":["index_exports","__export","MarkerDebugList","useGoogleMapsAttachment","useMapFirst","useMapFirstCore","useMapFirstProperties","useMapFirstSelectedProperty","useMapLibreAttachment","useMapboxAttachment","usePrimaryType","useSelectedMarker","__toCommonJS","import_react","import_core","import_jsx_runtime","options","instanceRef","React","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","center","zoom","location","loading","searching","instance","mapFirst","setProperties","selectedId","setSelectedId","primaryType","setPrimaryTypeState","setPrimaryType","selectedMarker","setSelectedMarkerState","setSelectedMarker","map","maplibregl","onMarkerClick","attachedRef","google","mapboxgl","markers","marker","_c","_d","_e","_f"]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n// Import additional types for search functionality\ntype InitialRequestBody = {\n initial?: boolean;\n query?: string;\n bounds?: {\n sw: { lat: number; lng: number };\n ne: { lat: number; lng: number };\n };\n filters?: any;\n city?: string;\n country?: string;\n location_id?: number;\n longitude?: number;\n latitude?: number;\n radius?: number;\n};\n\ntype SmartFilter = {\n id: string;\n label: string;\n type:\n | \"amenity\"\n | \"hotelStyle\"\n | \"priceRange\"\n | \"minRating\"\n | \"starRating\"\n | \"primary_type\"\n | \"transformed_query\"\n | \"selected_restaurant_price_levels\";\n value: string;\n numericValue?: number;\n priceRange?: {\n min: number;\n max?: number;\n };\n propertyType?: PropertyType;\n priceLevels?: any[];\n};\n\n/**\n * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.\n * Supports two-phase initialization: create SDK first, attach map later.\n * Returns the instance and reactive state that updates when SDK state changes.\n *\n * @example\n * ```tsx\n * // Phase 1: Create SDK instance with location data\n * const { mapFirst, state } = useMapFirstCore({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state.properties); // Updates when properties change\n * console.log(state.isSearching); // Updates when search state changes\n *\n * // Phase 2: Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance && mapFirst) {\n * mapFirst.attachMap(mapLibreInstance, {\n * platform: \"maplibre\",\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance, mapFirst]);\n * ```\n */\nexport function useMapFirstCore(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { mapFirst: instanceRef.current, state };\n}\n\n/**\n * Hook to access reactive properties from MapFirst SDK.\n * Returns the current properties array that updates when properties change.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const properties = useMapFirstProperties(mapFirst);\n *\n * return <div>Found {properties.length} properties</div>;\n * ```\n */\nexport function useMapFirstProperties(\n mapFirst: MapFirstCore | null\n): Property[] {\n const [properties, setProperties] = React.useState<Property[]>([]);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setProperties([]);\n return;\n }\n\n // Initialize with current state\n setProperties(mapFirst.getState().properties);\n }, [mapFirst]);\n\n return properties;\n}\n\n/**\n * Hook to access the selected property ID from MapFirst SDK.\n * Returns the currently selected property ID that updates when selection changes.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const selectedId = useMapFirstSelectedProperty(mapFirst);\n *\n * return <div>Selected: {selectedId || 'None'}</div>;\n * ```\n */\nexport function useMapFirstSelectedProperty(\n mapFirst: MapFirstCore | null\n): number | null {\n const [selectedId, setSelectedId] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedId(null);\n return;\n }\n\n // Initialize with current state\n setSelectedId(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n return selectedId;\n}\n\n/**\n * Hook to access and control the primary property type.\n * Returns the current primary type and a setter function.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [primaryType, setPrimaryType] = usePrimaryType(mapFirst);\n *\n * return (\n * <select value={primaryType} onChange={(e) => setPrimaryType(e.target.value as PropertyType)}>\n * <option value=\"Accommodation\">Hotels</option>\n * <option value=\"Restaurant\">Restaurants</option>\n * <option value=\"Attraction\">Attractions</option>\n * </select>\n * );\n * ```\n */\nexport function usePrimaryType(\n mapFirst: MapFirstCore | null\n): [PropertyType, (type: PropertyType) => void] {\n const [primaryType, setPrimaryTypeState] =\n React.useState<PropertyType>(\"Accommodation\");\n\n React.useEffect(() => {\n if (!mapFirst) {\n setPrimaryTypeState(\"Accommodation\");\n return;\n }\n\n // Initialize with current state\n setPrimaryTypeState(mapFirst.getState().primary);\n }, [mapFirst]);\n\n const setPrimaryType = React.useCallback(\n (type: PropertyType) => {\n if (mapFirst) {\n mapFirst.setPrimaryType(type);\n setPrimaryTypeState(type);\n }\n },\n [mapFirst]\n );\n\n return [primaryType, setPrimaryType];\n}\n\n/**\n * Hook to access and control the selected marker.\n * Returns the current selected marker ID and a setter function.\n * Note: This hook requires the MapFirstCore instance. For simpler usage with reactive updates,\n * use state.selectedPropertyId from useMapFirstCore instead.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [selectedMarker, setSelectedMarker] = useSelectedMarker(mapFirst);\n *\n * return (\n * <div>\n * <p>Selected: {selectedMarker || 'None'}</p>\n * <button onClick={() => setSelectedMarker(null)}>Clear Selection</button>\n * </div>\n * );\n * ```\n */\nexport function useSelectedMarker(\n mapFirst: MapFirstCore | null\n): [number | null, (id: number | null) => void] {\n const [selectedMarker, setSelectedMarkerState] = React.useState<\n number | null\n >(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedMarkerState(null);\n return;\n }\n\n // Initialize with current state\n setSelectedMarkerState(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n const setSelectedMarker = React.useCallback(\n (id: number | null) => {\n if (mapFirst) {\n mapFirst.setSelectedMarker(id);\n }\n },\n [mapFirst]\n );\n\n return [selectedMarker, setSelectedMarker];\n}\n\n/**\n * Hook for MapLibre GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Paris\", country: \"France\" } });\n * const mapRef = useRef<maplibregl.Map | null>(null);\n *\n * useMapLibreAttachment({\n * mapFirst,\n * map: mapRef.current,\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * ```\n */\nexport function useMapLibreAttachment({\n mapFirst,\n map,\n maplibregl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n maplibregl: MapLibreNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, maplibregl, onMarkerClick]);\n}\n\n/**\n * Hook for Google Maps integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Tokyo\", country: \"Japan\" } });\n * const mapRef = useRef<google.maps.Map | null>(null);\n *\n * useGoogleMapsAttachment({\n * mapFirst,\n * map: mapRef.current,\n * google: window.google,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.isSearching);\n * ```\n */\nexport function useGoogleMapsAttachment({\n mapFirst,\n map,\n google,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n google: GoogleMapsNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, google, onMarkerClick]);\n}\n\n/**\n * Hook for Mapbox GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"London\", country: \"United Kingdom\" } });\n * const mapRef = useRef<mapboxgl.Map | null>(null);\n *\n * useMapboxAttachment({\n * mapFirst,\n * map: mapRef.current,\n * mapboxgl: mapboxgl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.filters);\n * ```\n */\nexport function useMapboxAttachment({\n mapFirst,\n map,\n mapboxgl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n mapboxgl: MapboxNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, mapboxgl, onMarkerClick]);\n}\n\n/**\n * Legacy hook that creates the MapFirstCore instance with a map immediately.\n * Use useMapFirstCore + useMap*Attachment hooks for better control.\n *\n * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead\n */\nexport function useMapFirst(options: MapFirstOptions | null) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n\n React.useEffect(() => {\n if (!options) {\n return undefined;\n }\n const instance = new MapFirstCore(options);\n instanceRef.current = instance;\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n };\n }, [options]);\n\n return instanceRef;\n}\n\n/**\n * Hook to run properties search with the MapFirst SDK.\n * Returns a function to trigger the search and loading state.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const { search, isLoading, error } = usePropertiesSearch(mapFirst);\n *\n * const handleSearch = async () => {\n * await search({\n * body: {\n * city: \"Paris\",\n * country: \"France\",\n * filters: {\n * checkIn: new Date(),\n * checkOut: new Date(Date.now() + 86400000),\n * numAdults: 2,\n * numRooms: 1\n * }\n * }\n * });\n * };\n * ```\n */\nexport function usePropertiesSearch(mapFirst: MapFirstCore | null) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n\n const search = React.useCallback(\n async (options: {\n body: InitialRequestBody;\n beforeApplyProperties?: (data: any) => {\n price?: any;\n limit?: number;\n };\n smartFiltersClearable?: boolean;\n }) => {\n if (!mapFirst) {\n const err = new Error(\"MapFirst instance not available\");\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await mapFirst.runPropertiesSearch({\n ...options,\n onError: (err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n },\n });\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [mapFirst]\n );\n\n return { search, isLoading, error };\n}\n\n/**\n * Hook to run smart filter search with the MapFirst SDK.\n * Returns a function to trigger the search and loading state.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const { search, isLoading, error } = useSmartFilterSearch(mapFirst);\n *\n * const handleSearch = async () => {\n * await search({\n * query: \"hotels near beach with pool\"\n * });\n * };\n *\n * // Or with filters\n * const handleFilterSearch = async () => {\n * await search({\n * filters: [\n * { id: \"pool\", label: \"Pool\", type: \"amenity\", value: \"pool\" },\n * { id: \"4star\", label: \"4 Star\", type: \"starRating\", value: \"4\", numericValue: 4 }\n * ]\n * });\n * };\n * ```\n */\nexport function useSmartFilterSearch(mapFirst: MapFirstCore | null) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n\n const search = React.useCallback(\n async (options: {\n query?: string;\n filters?: SmartFilter[];\n onProcessFilters?: (\n filters: any,\n location_id?: number\n ) => {\n smartFilters?: SmartFilter[];\n price?: any;\n limit?: number;\n language?: string;\n };\n }) => {\n if (!mapFirst) {\n const err = new Error(\"MapFirst instance not available\");\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await mapFirst.runSmartFilterSearch({\n ...options,\n onError: (err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n },\n });\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [mapFirst]\n );\n\n return { search, isLoading, error };\n}\n\n/**\n * Helper component that simply renders the markers it receives so non-React environments\n * can verify data flows before wiring the SDK into a map.\n */\nexport function MarkerDebugList({ markers }: { markers: Property[] }) {\n return (\n <div style={{ fontFamily: \"sans-serif\", fontSize: 14 }}>\n <strong>Markers</strong>\n <ul>\n {markers.map((marker) => (\n <li key={String(marker.tripadvisor_id)}>\n {marker.name} — {marker.location?.lat?.toFixed(3) ?? \"n/a\"},{\" \"}\n {marker.location?.lon?.toFixed(3) ?? \"n/a\"}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":"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","names":["index_exports","__export","MarkerDebugList","useGoogleMapsAttachment","useMapFirst","useMapFirstCore","useMapFirstProperties","useMapFirstSelectedProperty","useMapLibreAttachment","useMapboxAttachment","usePrimaryType","usePropertiesSearch","useSelectedMarker","useSmartFilterSearch","__toCommonJS","import_react","import_core","import_jsx_runtime","options","instanceRef","React","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","center","zoom","location","loading","searching","instance","mapFirst","setProperties","selectedId","setSelectedId","primaryType","setPrimaryTypeState","setPrimaryType","selectedMarker","setSelectedMarkerState","setSelectedMarker","map","maplibregl","onMarkerClick","attachedRef","google","mapboxgl","isLoading","setIsLoading","error","setError","err","markers","marker","_c","_d","_e","_f"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import s from"react";import{MapFirstCore as g}from"@mapfirst.ai/core";import{jsx as d,jsxs as M}from"react/jsx-runtime";function h(t){let n=s.useRef(null),[a,c]=s.useState(null),o=s.useRef(t);return s.useEffect(()=>{o.current=t}),s.useEffect(()=>{let p=o.current,f={adapter:null,...p,callbacks:{...p.callbacks,onPropertiesChange:l=>{var e,r;c(u=>u?{...u,properties:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onPropertiesChange)==null||r.call(e,l)},onSelectedPropertyChange:l=>{var e,r;c(u=>u?{...u,selectedPropertyId:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onSelectedPropertyChange)==null||r.call(e,l)},onPrimaryTypeChange:l=>{var e,r;c(u=>u?{...u,primary:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onPrimaryTypeChange)==null||r.call(e,l)},onFiltersChange:l=>{var e,r;c(u=>u?{...u,filters:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onFiltersChange)==null||r.call(e,l)},onBoundsChange:l=>{var e,r;c(u=>u?{...u,bounds:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onBoundsChange)==null||r.call(e,l)},onCenterChange:(l,e)=>{var r,u;c(y=>y?{...y,center:l,zoom:e}:null),(u=(r=o.current.callbacks)==null?void 0:r.onCenterChange)==null||u.call(r,l,e)},onZoomChange:l=>{var e,r;c(u=>u?{...u,zoom:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onZoomChange)==null||r.call(e,l)},onActiveLocationChange:l=>{var e,r;c(u=>u?{...u,activeLocation:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onActiveLocationChange)==null||r.call(e,l)},onLoadingStateChange:l=>{var e,r;c(u=>u?{...u,initialLoading:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onLoadingStateChange)==null||r.call(e,l)},onSearchingStateChange:l=>{var e,r;c(u=>u?{...u,isSearching:l}:null),(r=(e=o.current.callbacks)==null?void 0:e.onSearchingStateChange)==null||r.call(e,l)}}},i=new g(f);return n.current=i,c(i.getState()),()=>{i.destroy(),n.current=null,c(null)}},[]),{mapFirst:n.current,state:a}}function b(t){let[n,a]=s.useState([]);return s.useEffect(()=>{if(!t){a([]);return}a(t.getState().properties)},[t]),n}function P(t){let[n,a]=s.useState(null);return s.useEffect(()=>{if(!t){a(null);return}a(t.getState().selectedPropertyId)},[t]),n}function k(t){let[n,a]=s.useState("Accommodation");s.useEffect(()=>{if(!t){a("Accommodation");return}a(t.getState().primary)},[t]);let c=s.useCallback(o=>{t&&(t.setPrimaryType(o),a(o))},[t]);return[n,c]}function m(t){let[n,a]=s.useState(null);s.useEffect(()=>{if(!t){a(null);return}a(t.getState().selectedPropertyId)},[t]);let c=s.useCallback(o=>{t&&t.setSelectedMarker(o)},[t]);return[n,c]}function x({mapFirst:t,map:n,maplibregl:a,onMarkerClick:c}){let o=s.useRef(!1);s.useEffect(()=>{!t||!n||o.current||(t.attachMap(n,{platform:"maplibre",maplibregl:a,onMarkerClick:c}),o.current=!0)},[t,n,a,c])}function R({mapFirst:t,map:n,google:a,onMarkerClick:c}){let o=s.useRef(!1);s.useEffect(()=>{!t||!n||o.current||(t.attachMap(n,{platform:"google",google:a,onMarkerClick:c}),o.current=!0)},[t,n,a,c])}function T({mapFirst:t,map:n,mapboxgl:a,onMarkerClick:c}){let o=s.useRef(!1);s.useEffect(()=>{!t||!n||o.current||(t.attachMap(n,{platform:"mapbox",mapboxgl:a,onMarkerClick:c}),o.current=!0)},[t,n,a,c])}function E(t){let n=s.useRef(null);return s.useEffect(()=>{if(!t)return;let a=new g(t);return n.current=a,()=>{a.destroy(),n.current=null}},[t]),n}function L({markers:t}){return M("div",{style:{fontFamily:"sans-serif",fontSize:14},children:[d("strong",{children:"Markers"}),d("ul",{children:t.map(n=>{var a,c,o,p,f,i;return M("li",{children:[n.name," \u2014 ",(o=(c=(a=n.location)==null?void 0:a.lat)==null?void 0:c.toFixed(3))!=null?o:"n/a",","," ",(i=(f=(p=n.location)==null?void 0:p.lon)==null?void 0:f.toFixed(3))!=null?i:"n/a"]},String(n.tripadvisor_id))})})]})}export{L as MarkerDebugList,R as useGoogleMapsAttachment,E as useMapFirst,h as useMapFirstCore,b as useMapFirstProperties,P as useMapFirstSelectedProperty,x as useMapLibreAttachment,T as useMapboxAttachment,k as usePrimaryType,m as useSelectedMarker};
1
+ import c from"react";import{MapFirstCore as b}from"@mapfirst.ai/core";import{jsx as g,jsxs as d}from"react/jsx-runtime";function h(r){let a=c.useRef(null),[o,l]=c.useState(null),n=c.useRef(r);return c.useEffect(()=>{n.current=r}),c.useEffect(()=>{let y=n.current,p={adapter:null,...y,callbacks:{...y.callbacks,onPropertiesChange:t=>{var e,s;l(u=>u?{...u,properties:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onPropertiesChange)==null||s.call(e,t)},onSelectedPropertyChange:t=>{var e,s;l(u=>u?{...u,selectedPropertyId:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onSelectedPropertyChange)==null||s.call(e,t)},onPrimaryTypeChange:t=>{var e,s;l(u=>u?{...u,primary:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onPrimaryTypeChange)==null||s.call(e,t)},onFiltersChange:t=>{var e,s;l(u=>u?{...u,filters:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onFiltersChange)==null||s.call(e,t)},onBoundsChange:t=>{var e,s;l(u=>u?{...u,bounds:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onBoundsChange)==null||s.call(e,t)},onCenterChange:(t,e)=>{var s,u;l(f=>f?{...f,center:t,zoom:e}:null),(u=(s=n.current.callbacks)==null?void 0:s.onCenterChange)==null||u.call(s,t,e)},onZoomChange:t=>{var e,s;l(u=>u?{...u,zoom:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onZoomChange)==null||s.call(e,t)},onActiveLocationChange:t=>{var e,s;l(u=>u?{...u,activeLocation:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onActiveLocationChange)==null||s.call(e,t)},onLoadingStateChange:t=>{var e,s;l(u=>u?{...u,initialLoading:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onLoadingStateChange)==null||s.call(e,t)},onSearchingStateChange:t=>{var e,s;l(u=>u?{...u,isSearching:t}:null),(s=(e=n.current.callbacks)==null?void 0:e.onSearchingStateChange)==null||s.call(e,t)}}},i=new b(p);return a.current=i,l(i.getState()),()=>{i.destroy(),a.current=null,l(null)}},[]),{mapFirst:a.current,state:o}}function M(r){let[a,o]=c.useState([]);return c.useEffect(()=>{if(!r){o([]);return}o(r.getState().properties)},[r]),a}function C(r){let[a,o]=c.useState(null);return c.useEffect(()=>{if(!r){o(null);return}o(r.getState().selectedPropertyId)},[r]),a}function P(r){let[a,o]=c.useState("Accommodation");c.useEffect(()=>{if(!r){o("Accommodation");return}o(r.getState().primary)},[r]);let l=c.useCallback(n=>{r&&(r.setPrimaryType(n),o(n))},[r]);return[a,l]}function E(r){let[a,o]=c.useState(null);c.useEffect(()=>{if(!r){o(null);return}o(r.getState().selectedPropertyId)},[r]);let l=c.useCallback(n=>{r&&r.setSelectedMarker(n)},[r]);return[a,l]}function k({mapFirst:r,map:a,maplibregl:o,onMarkerClick:l}){let n=c.useRef(!1);c.useEffect(()=>{!r||!a||n.current||(r.attachMap(a,{platform:"maplibre",maplibregl:o,onMarkerClick:l}),n.current=!0)},[r,a,o,l])}function R({mapFirst:r,map:a,google:o,onMarkerClick:l}){let n=c.useRef(!1);c.useEffect(()=>{!r||!a||n.current||(r.attachMap(a,{platform:"google",google:o,onMarkerClick:l}),n.current=!0)},[r,a,o,l])}function x({mapFirst:r,map:a,mapboxgl:o,onMarkerClick:l}){let n=c.useRef(!1);c.useEffect(()=>{!r||!a||n.current||(r.attachMap(a,{platform:"mapbox",mapboxgl:o,onMarkerClick:l}),n.current=!0)},[r,a,o,l])}function F(r){let a=c.useRef(null);return c.useEffect(()=>{if(!r)return;let o=new b(r);return a.current=o,()=>{o.destroy(),a.current=null}},[r]),a}function w(r){let[a,o]=c.useState(!1),[l,n]=c.useState(null);return{search:c.useCallback(async p=>{if(!r){let i=new Error("MapFirst instance not available");throw n(i),i}o(!0),n(null);try{return await r.runPropertiesSearch({...p,onError:t=>{let e=t instanceof Error?t:new Error(String(t));n(e)}})}catch(i){let t=i instanceof Error?i:new Error(String(i));throw n(t),t}finally{o(!1)}},[r]),isLoading:a,error:l}}function L(r){let[a,o]=c.useState(!1),[l,n]=c.useState(null);return{search:c.useCallback(async p=>{if(!r){let i=new Error("MapFirst instance not available");throw n(i),i}o(!0),n(null);try{return await r.runSmartFilterSearch({...p,onError:t=>{let e=t instanceof Error?t:new Error(String(t));n(e)}})}catch(i){let t=i instanceof Error?i:new Error(String(i));throw n(t),t}finally{o(!1)}},[r]),isLoading:a,error:l}}function T({markers:r}){return d("div",{style:{fontFamily:"sans-serif",fontSize:14},children:[g("strong",{children:"Markers"}),g("ul",{children:r.map(a=>{var o,l,n,y,p,i;return d("li",{children:[a.name," \u2014 ",(n=(l=(o=a.location)==null?void 0:o.lat)==null?void 0:l.toFixed(3))!=null?n:"n/a",","," ",(i=(p=(y=a.location)==null?void 0:y.lon)==null?void 0:p.toFixed(3))!=null?i:"n/a"]},String(a.tripadvisor_id))})})]})}export{T as MarkerDebugList,R as useGoogleMapsAttachment,F as useMapFirst,h as useMapFirstCore,M as useMapFirstProperties,C as useMapFirstSelectedProperty,k as useMapLibreAttachment,x as useMapboxAttachment,P as usePrimaryType,w as usePropertiesSearch,E as useSelectedMarker,L as useSmartFilterSearch};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n/**\n * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.\n * Supports two-phase initialization: create SDK first, attach map later.\n * Returns the instance and reactive state that updates when SDK state changes.\n *\n * @example\n * ```tsx\n * // Phase 1: Create SDK instance with location data\n * const { mapFirst, state } = useMapFirstCore({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state.properties); // Updates when properties change\n * console.log(state.isSearching); // Updates when search state changes\n *\n * // Phase 2: Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance && mapFirst) {\n * mapFirst.attachMap(mapLibreInstance, {\n * platform: \"maplibre\",\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance, mapFirst]);\n * ```\n */\nexport function useMapFirstCore(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { mapFirst: instanceRef.current, state };\n}\n\n/**\n * Hook to access reactive properties from MapFirst SDK.\n * Returns the current properties array that updates when properties change.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const properties = useMapFirstProperties(mapFirst);\n *\n * return <div>Found {properties.length} properties</div>;\n * ```\n */\nexport function useMapFirstProperties(\n mapFirst: MapFirstCore | null\n): Property[] {\n const [properties, setProperties] = React.useState<Property[]>([]);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setProperties([]);\n return;\n }\n\n // Initialize with current state\n setProperties(mapFirst.getState().properties);\n }, [mapFirst]);\n\n return properties;\n}\n\n/**\n * Hook to access the selected property ID from MapFirst SDK.\n * Returns the currently selected property ID that updates when selection changes.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const selectedId = useMapFirstSelectedProperty(mapFirst);\n *\n * return <div>Selected: {selectedId || 'None'}</div>;\n * ```\n */\nexport function useMapFirstSelectedProperty(\n mapFirst: MapFirstCore | null\n): number | null {\n const [selectedId, setSelectedId] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedId(null);\n return;\n }\n\n // Initialize with current state\n setSelectedId(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n return selectedId;\n}\n\n/**\n * Hook to access and control the primary property type.\n * Returns the current primary type and a setter function.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [primaryType, setPrimaryType] = usePrimaryType(mapFirst);\n *\n * return (\n * <select value={primaryType} onChange={(e) => setPrimaryType(e.target.value as PropertyType)}>\n * <option value=\"Accommodation\">Hotels</option>\n * <option value=\"Restaurant\">Restaurants</option>\n * <option value=\"Attraction\">Attractions</option>\n * </select>\n * );\n * ```\n */\nexport function usePrimaryType(\n mapFirst: MapFirstCore | null\n): [PropertyType, (type: PropertyType) => void] {\n const [primaryType, setPrimaryTypeState] =\n React.useState<PropertyType>(\"Accommodation\");\n\n React.useEffect(() => {\n if (!mapFirst) {\n setPrimaryTypeState(\"Accommodation\");\n return;\n }\n\n // Initialize with current state\n setPrimaryTypeState(mapFirst.getState().primary);\n }, [mapFirst]);\n\n const setPrimaryType = React.useCallback(\n (type: PropertyType) => {\n if (mapFirst) {\n mapFirst.setPrimaryType(type);\n setPrimaryTypeState(type);\n }\n },\n [mapFirst]\n );\n\n return [primaryType, setPrimaryType];\n}\n\n/**\n * Hook to access and control the selected marker.\n * Returns the current selected marker ID and a setter function.\n * Note: This hook requires the MapFirstCore instance. For simpler usage with reactive updates,\n * use state.selectedPropertyId from useMapFirstCore instead.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [selectedMarker, setSelectedMarker] = useSelectedMarker(mapFirst);\n *\n * return (\n * <div>\n * <p>Selected: {selectedMarker || 'None'}</p>\n * <button onClick={() => setSelectedMarker(null)}>Clear Selection</button>\n * </div>\n * );\n * ```\n */\nexport function useSelectedMarker(\n mapFirst: MapFirstCore | null\n): [number | null, (id: number | null) => void] {\n const [selectedMarker, setSelectedMarkerState] = React.useState<\n number | null\n >(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedMarkerState(null);\n return;\n }\n\n // Initialize with current state\n setSelectedMarkerState(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n const setSelectedMarker = React.useCallback(\n (id: number | null) => {\n if (mapFirst) {\n mapFirst.setSelectedMarker(id);\n }\n },\n [mapFirst]\n );\n\n return [selectedMarker, setSelectedMarker];\n}\n\n/**\n * Hook for MapLibre GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Paris\", country: \"France\" } });\n * const mapRef = useRef<maplibregl.Map | null>(null);\n *\n * useMapLibreAttachment({\n * mapFirst,\n * map: mapRef.current,\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * ```\n */\nexport function useMapLibreAttachment({\n mapFirst,\n map,\n maplibregl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n maplibregl: MapLibreNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, maplibregl, onMarkerClick]);\n}\n\n/**\n * Hook for Google Maps integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Tokyo\", country: \"Japan\" } });\n * const mapRef = useRef<google.maps.Map | null>(null);\n *\n * useGoogleMapsAttachment({\n * mapFirst,\n * map: mapRef.current,\n * google: window.google,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.isSearching);\n * ```\n */\nexport function useGoogleMapsAttachment({\n mapFirst,\n map,\n google,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n google: GoogleMapsNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, google, onMarkerClick]);\n}\n\n/**\n * Hook for Mapbox GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"London\", country: \"United Kingdom\" } });\n * const mapRef = useRef<mapboxgl.Map | null>(null);\n *\n * useMapboxAttachment({\n * mapFirst,\n * map: mapRef.current,\n * mapboxgl: mapboxgl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.filters);\n * ```\n */\nexport function useMapboxAttachment({\n mapFirst,\n map,\n mapboxgl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n mapboxgl: MapboxNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, mapboxgl, onMarkerClick]);\n}\n\n/**\n * Legacy hook that creates the MapFirstCore instance with a map immediately.\n * Use useMapFirstCore + useMap*Attachment hooks for better control.\n *\n * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead\n */\nexport function useMapFirst(options: MapFirstOptions | null) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n\n React.useEffect(() => {\n if (!options) {\n return undefined;\n }\n const instance = new MapFirstCore(options);\n instanceRef.current = instance;\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n };\n }, [options]);\n\n return instanceRef;\n}\n\n/**\n * Helper component that simply renders the markers it receives so non-React environments\n * can verify data flows before wiring the SDK into a map.\n */\nexport function MarkerDebugList({ markers }: { markers: Property[] }) {\n return (\n <div style={{ fontFamily: \"sans-serif\", fontSize: 14 }}>\n <strong>Markers</strong>\n <ul>\n {markers.map((marker) => (\n <li key={String(marker.tripadvisor_id)}>\n {marker.name} — {marker.location?.lat?.toFixed(3) ?? \"n/a\"},{\" \"}\n {marker.location?.lon?.toFixed(3) ?? \"n/a\"}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":"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","names":["React","MapFirstCore","jsx","jsxs","useMapFirstCore","options","instanceRef","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","center","zoom","location","loading","searching","instance","useMapFirstProperties","mapFirst","setProperties","useMapFirstSelectedProperty","selectedId","setSelectedId","usePrimaryType","primaryType","setPrimaryTypeState","setPrimaryType","useSelectedMarker","selectedMarker","setSelectedMarkerState","setSelectedMarker","useMapLibreAttachment","map","maplibregl","onMarkerClick","attachedRef","useGoogleMapsAttachment","google","useMapboxAttachment","mapboxgl","useMapFirst","MarkerDebugList","markers","marker","_c","_d","_e","_f"]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n// Import additional types for search functionality\ntype InitialRequestBody = {\n initial?: boolean;\n query?: string;\n bounds?: {\n sw: { lat: number; lng: number };\n ne: { lat: number; lng: number };\n };\n filters?: any;\n city?: string;\n country?: string;\n location_id?: number;\n longitude?: number;\n latitude?: number;\n radius?: number;\n};\n\ntype SmartFilter = {\n id: string;\n label: string;\n type:\n | \"amenity\"\n | \"hotelStyle\"\n | \"priceRange\"\n | \"minRating\"\n | \"starRating\"\n | \"primary_type\"\n | \"transformed_query\"\n | \"selected_restaurant_price_levels\";\n value: string;\n numericValue?: number;\n priceRange?: {\n min: number;\n max?: number;\n };\n propertyType?: PropertyType;\n priceLevels?: any[];\n};\n\n/**\n * Hook that creates a MapFirstCore instance that can be initialized before maps are ready.\n * Supports two-phase initialization: create SDK first, attach map later.\n * Returns the instance and reactive state that updates when SDK state changes.\n *\n * @example\n * ```tsx\n * // Phase 1: Create SDK instance with location data\n * const { mapFirst, state } = useMapFirstCore({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state.properties); // Updates when properties change\n * console.log(state.isSearching); // Updates when search state changes\n *\n * // Phase 2: Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance && mapFirst) {\n * mapFirst.attachMap(mapLibreInstance, {\n * platform: \"maplibre\",\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance, mapFirst]);\n * ```\n */\nexport function useMapFirstCore(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { mapFirst: instanceRef.current, state };\n}\n\n/**\n * Hook to access reactive properties from MapFirst SDK.\n * Returns the current properties array that updates when properties change.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const properties = useMapFirstProperties(mapFirst);\n *\n * return <div>Found {properties.length} properties</div>;\n * ```\n */\nexport function useMapFirstProperties(\n mapFirst: MapFirstCore | null\n): Property[] {\n const [properties, setProperties] = React.useState<Property[]>([]);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setProperties([]);\n return;\n }\n\n // Initialize with current state\n setProperties(mapFirst.getState().properties);\n }, [mapFirst]);\n\n return properties;\n}\n\n/**\n * Hook to access the selected property ID from MapFirst SDK.\n * Returns the currently selected property ID that updates when selection changes.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const selectedId = useMapFirstSelectedProperty(mapFirst);\n *\n * return <div>Selected: {selectedId || 'None'}</div>;\n * ```\n */\nexport function useMapFirstSelectedProperty(\n mapFirst: MapFirstCore | null\n): number | null {\n const [selectedId, setSelectedId] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedId(null);\n return;\n }\n\n // Initialize with current state\n setSelectedId(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n return selectedId;\n}\n\n/**\n * Hook to access and control the primary property type.\n * Returns the current primary type and a setter function.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [primaryType, setPrimaryType] = usePrimaryType(mapFirst);\n *\n * return (\n * <select value={primaryType} onChange={(e) => setPrimaryType(e.target.value as PropertyType)}>\n * <option value=\"Accommodation\">Hotels</option>\n * <option value=\"Restaurant\">Restaurants</option>\n * <option value=\"Attraction\">Attractions</option>\n * </select>\n * );\n * ```\n */\nexport function usePrimaryType(\n mapFirst: MapFirstCore | null\n): [PropertyType, (type: PropertyType) => void] {\n const [primaryType, setPrimaryTypeState] =\n React.useState<PropertyType>(\"Accommodation\");\n\n React.useEffect(() => {\n if (!mapFirst) {\n setPrimaryTypeState(\"Accommodation\");\n return;\n }\n\n // Initialize with current state\n setPrimaryTypeState(mapFirst.getState().primary);\n }, [mapFirst]);\n\n const setPrimaryType = React.useCallback(\n (type: PropertyType) => {\n if (mapFirst) {\n mapFirst.setPrimaryType(type);\n setPrimaryTypeState(type);\n }\n },\n [mapFirst]\n );\n\n return [primaryType, setPrimaryType];\n}\n\n/**\n * Hook to access and control the selected marker.\n * Returns the current selected marker ID and a setter function.\n * Note: This hook requires the MapFirstCore instance. For simpler usage with reactive updates,\n * use state.selectedPropertyId from useMapFirstCore instead.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const [selectedMarker, setSelectedMarker] = useSelectedMarker(mapFirst);\n *\n * return (\n * <div>\n * <p>Selected: {selectedMarker || 'None'}</p>\n * <button onClick={() => setSelectedMarker(null)}>Clear Selection</button>\n * </div>\n * );\n * ```\n */\nexport function useSelectedMarker(\n mapFirst: MapFirstCore | null\n): [number | null, (id: number | null) => void] {\n const [selectedMarker, setSelectedMarkerState] = React.useState<\n number | null\n >(null);\n\n React.useEffect(() => {\n if (!mapFirst) {\n setSelectedMarkerState(null);\n return;\n }\n\n // Initialize with current state\n setSelectedMarkerState(mapFirst.getState().selectedPropertyId);\n }, [mapFirst]);\n\n const setSelectedMarker = React.useCallback(\n (id: number | null) => {\n if (mapFirst) {\n mapFirst.setSelectedMarker(id);\n }\n },\n [mapFirst]\n );\n\n return [selectedMarker, setSelectedMarker];\n}\n\n/**\n * Hook for MapLibre GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Paris\", country: \"France\" } });\n * const mapRef = useRef<maplibregl.Map | null>(null);\n *\n * useMapLibreAttachment({\n * mapFirst,\n * map: mapRef.current,\n * maplibregl: maplibregl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * ```\n */\nexport function useMapLibreAttachment({\n mapFirst,\n map,\n maplibregl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n maplibregl: MapLibreNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, maplibregl, onMarkerClick]);\n}\n\n/**\n * Hook for Google Maps integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"Tokyo\", country: \"Japan\" } });\n * const mapRef = useRef<google.maps.Map | null>(null);\n *\n * useGoogleMapsAttachment({\n * mapFirst,\n * map: mapRef.current,\n * google: window.google,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.isSearching);\n * ```\n */\nexport function useGoogleMapsAttachment({\n mapFirst,\n map,\n google,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n google: GoogleMapsNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, google, onMarkerClick]);\n}\n\n/**\n * Hook for Mapbox GL JS integration.\n * Automatically attaches the map when both the SDK instance and map are available.\n *\n * @example\n * ```tsx\n * const { mapFirst, state } = useMapFirstCore({ initialLocationData: { city: \"London\", country: \"United Kingdom\" } });\n * const mapRef = useRef<mapboxgl.Map | null>(null);\n *\n * useMapboxAttachment({\n * mapFirst,\n * map: mapRef.current,\n * mapboxgl: mapboxgl,\n * onMarkerClick: (marker) => console.log(marker)\n * });\n *\n * // Access reactive state\n * console.log(state?.filters);\n * ```\n */\nexport function useMapboxAttachment({\n mapFirst,\n map,\n mapboxgl,\n onMarkerClick,\n}: {\n mapFirst: MapFirstCore | null;\n map: any | null;\n mapboxgl: MapboxNamespace;\n onMarkerClick?: (marker: Property) => void;\n}) {\n const attachedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!mapFirst || !map || attachedRef.current) {\n return;\n }\n\n mapFirst.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick,\n });\n\n attachedRef.current = true;\n }, [mapFirst, map, mapboxgl, onMarkerClick]);\n}\n\n/**\n * Legacy hook that creates the MapFirstCore instance with a map immediately.\n * Use useMapFirstCore + useMap*Attachment hooks for better control.\n *\n * @deprecated Use useMapFirstCore and platform-specific attachment hooks instead\n */\nexport function useMapFirst(options: MapFirstOptions | null) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n\n React.useEffect(() => {\n if (!options) {\n return undefined;\n }\n const instance = new MapFirstCore(options);\n instanceRef.current = instance;\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n };\n }, [options]);\n\n return instanceRef;\n}\n\n/**\n * Hook to run properties search with the MapFirst SDK.\n * Returns a function to trigger the search and loading state.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const { search, isLoading, error } = usePropertiesSearch(mapFirst);\n *\n * const handleSearch = async () => {\n * await search({\n * body: {\n * city: \"Paris\",\n * country: \"France\",\n * filters: {\n * checkIn: new Date(),\n * checkOut: new Date(Date.now() + 86400000),\n * numAdults: 2,\n * numRooms: 1\n * }\n * }\n * });\n * };\n * ```\n */\nexport function usePropertiesSearch(mapFirst: MapFirstCore | null) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n\n const search = React.useCallback(\n async (options: {\n body: InitialRequestBody;\n beforeApplyProperties?: (data: any) => {\n price?: any;\n limit?: number;\n };\n smartFiltersClearable?: boolean;\n }) => {\n if (!mapFirst) {\n const err = new Error(\"MapFirst instance not available\");\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await mapFirst.runPropertiesSearch({\n ...options,\n onError: (err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n },\n });\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [mapFirst]\n );\n\n return { search, isLoading, error };\n}\n\n/**\n * Hook to run smart filter search with the MapFirst SDK.\n * Returns a function to trigger the search and loading state.\n *\n * @example\n * ```tsx\n * const { mapFirst } = useMapFirstCore({ ... });\n * const { search, isLoading, error } = useSmartFilterSearch(mapFirst);\n *\n * const handleSearch = async () => {\n * await search({\n * query: \"hotels near beach with pool\"\n * });\n * };\n *\n * // Or with filters\n * const handleFilterSearch = async () => {\n * await search({\n * filters: [\n * { id: \"pool\", label: \"Pool\", type: \"amenity\", value: \"pool\" },\n * { id: \"4star\", label: \"4 Star\", type: \"starRating\", value: \"4\", numericValue: 4 }\n * ]\n * });\n * };\n * ```\n */\nexport function useSmartFilterSearch(mapFirst: MapFirstCore | null) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n\n const search = React.useCallback(\n async (options: {\n query?: string;\n filters?: SmartFilter[];\n onProcessFilters?: (\n filters: any,\n location_id?: number\n ) => {\n smartFilters?: SmartFilter[];\n price?: any;\n limit?: number;\n language?: string;\n };\n }) => {\n if (!mapFirst) {\n const err = new Error(\"MapFirst instance not available\");\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await mapFirst.runSmartFilterSearch({\n ...options,\n onError: (err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n },\n });\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [mapFirst]\n );\n\n return { search, isLoading, error };\n}\n\n/**\n * Helper component that simply renders the markers it receives so non-React environments\n * can verify data flows before wiring the SDK into a map.\n */\nexport function MarkerDebugList({ markers }: { markers: Property[] }) {\n return (\n <div style={{ fontFamily: \"sans-serif\", fontSize: 14 }}>\n <strong>Markers</strong>\n <ul>\n {markers.map((marker) => (\n <li key={String(marker.tripadvisor_id)}>\n {marker.name} — {marker.location?.lat?.toFixed(3) ?? \"n/a\"},{\" \"}\n {marker.location?.lon?.toFixed(3) ?? \"n/a\"}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":"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","names":["React","MapFirstCore","jsx","jsxs","useMapFirstCore","options","instanceRef","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","center","zoom","location","loading","searching","instance","useMapFirstProperties","mapFirst","setProperties","useMapFirstSelectedProperty","selectedId","setSelectedId","usePrimaryType","primaryType","setPrimaryTypeState","setPrimaryType","useSelectedMarker","selectedMarker","setSelectedMarkerState","setSelectedMarker","useMapLibreAttachment","map","maplibregl","onMarkerClick","attachedRef","useGoogleMapsAttachment","google","useMapboxAttachment","mapboxgl","useMapFirst","usePropertiesSearch","isLoading","setIsLoading","error","setError","err","useSmartFilterSearch","MarkerDebugList","markers","marker","_c","_d","_e","_f"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapfirst.ai/react",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "React hooks for MapFirst SDK - Reactive state management for map properties",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -40,7 +40,7 @@
40
40
  "react": ">=17 || >=18"
41
41
  },
42
42
  "dependencies": {
43
- "@mapfirst.ai/core": "0.0.4"
43
+ "@mapfirst.ai/core": "0.0.6"
44
44
  },
45
45
  "scripts": {
46
46
  "build": "tsup src/index.tsx --format esm,cjs --dts --sourcemap --clean"