react-listing-engine 0.6.10 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/chunk-3O6X563H.cjs +2 -0
- package/dist/chunk-SIMKBYC6.js +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +74 -14
- package/dist/index.d.ts +74 -14
- package/dist/index.js +1 -1
- package/dist/{listing-app-CtF5E1ja.d.cts → listing-app-C7EeHlmP.d.cts} +14 -3
- package/dist/{listing-app-BeYPcPVw.d.ts → listing-app-DHFJtnKI.d.ts} +14 -3
- package/dist/map-provider.interface-B5Law7gE.d.cts +143 -0
- package/dist/map-provider.interface-B5Law7gE.d.ts +143 -0
- package/dist/maps/google/index.cjs +1 -1
- package/dist/maps/google/index.d.cts +1 -1
- package/dist/maps/google/index.d.ts +1 -1
- package/dist/maps/google/index.js +1 -1
- package/dist/styled/index.cjs +1 -1
- package/dist/styled/index.d.cts +3 -3
- package/dist/styled/index.d.ts +3 -3
- package/dist/styled/index.js +1 -1
- package/dist/testing/index.cjs +2 -2
- package/dist/testing/index.d.cts +37 -1
- package/dist/testing/index.d.ts +37 -1
- package/dist/testing/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CZCVR4OW.js +0 -2
- package/dist/chunk-KJW54NRT.cjs +0 -2
- package/dist/map-provider.interface-DT-v1plm.d.cts +0 -67
- package/dist/map-provider.interface-DT-v1plm.d.ts +0 -67
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import { b as EntityAdapter, M as MapPoint, L as LatLng, a as MapProvider } from './map-provider.interface-
|
|
3
|
+
import { b as EntityAdapter, M as MapPoint, L as LatLng, a as MapProvider } from './map-provider.interface-B5Law7gE.cjs';
|
|
4
4
|
|
|
5
5
|
interface FilterControlProps<TValue> {
|
|
6
6
|
value: TValue;
|
|
@@ -119,6 +119,7 @@ interface IListingComponents {
|
|
|
119
119
|
ResultHeader: ComponentType<IListingResultHeaderProps>;
|
|
120
120
|
Toolbar: ComponentType<IListingToolbarProps>;
|
|
121
121
|
}
|
|
122
|
+
declare const FallbackPopup: ComponentType<IListingPopupProps>;
|
|
122
123
|
/**
|
|
123
124
|
* Injection point for custom-component overrides. Every slot is optional —
|
|
124
125
|
* anything not provided falls back to the (unstyled) default. Mirrors
|
|
@@ -189,6 +190,8 @@ interface IStyledListingLayoutProps {
|
|
|
189
190
|
mapCenter?: LatLng;
|
|
190
191
|
/** Forwarded verbatim to `<ListingMap zoom={mapZoom} />`. */
|
|
191
192
|
mapZoom?: number;
|
|
193
|
+
/** Forwarded verbatim to `<ListingMap mapControls={mapControls} />` -- see that prop's doc comment. */
|
|
194
|
+
mapControls?: ReactNode;
|
|
192
195
|
className?: string;
|
|
193
196
|
}
|
|
194
197
|
/**
|
|
@@ -235,7 +238,7 @@ interface IStyledListingLayoutProps {
|
|
|
235
238
|
* default -- pass `autoFetch={false}`
|
|
236
239
|
* to opt out and drive the first fetch yourself.
|
|
237
240
|
*/
|
|
238
|
-
declare function StyledListingLayout({ search, toolbarEnd, mobileAction, autoFetch, hasMap: hasMapProp, mapCenter, mapZoom, className, }: IStyledListingLayoutProps): react.JSX.Element;
|
|
241
|
+
declare function StyledListingLayout({ search, toolbarEnd, mobileAction, autoFetch, hasMap: hasMapProp, mapCenter, mapZoom, mapControls, className, }: IStyledListingLayoutProps): react.JSX.Element;
|
|
239
242
|
|
|
240
243
|
/**
|
|
241
244
|
* Two-shape `map` prop: pass a ready `MapProvider`, or the `{ apiKey, mapId? }`
|
|
@@ -309,6 +312,14 @@ interface ListingAppProps<TFilters> {
|
|
|
309
312
|
mobileAction?: IBottomNavAction;
|
|
310
313
|
search?: IStyledListingLayoutProps['search'];
|
|
311
314
|
toolbarEnd?: IStyledListingLayoutProps['toolbarEnd'];
|
|
315
|
+
/**
|
|
316
|
+
* Rendered as an absolutely-positioned overlay floating over the map (e.g. zoom/fullscreen
|
|
317
|
+
* buttons) -- forwarded verbatim through `StyledListingLayout` to `ListingMap`'s own
|
|
318
|
+
* `mapControls` prop; see that prop's doc comment for the exact positioning contract. Omit
|
|
319
|
+
* (the default) to render nothing extra. Has no effect when no map is configured (the layout
|
|
320
|
+
* drops the map region entirely in that case).
|
|
321
|
+
*/
|
|
322
|
+
mapControls?: ReactNode;
|
|
312
323
|
config?: Partial<IListingConfigOptions>;
|
|
313
324
|
autoFetch?: boolean;
|
|
314
325
|
className?: string;
|
|
@@ -348,4 +359,4 @@ interface ListingAppProps<TFilters> {
|
|
|
348
359
|
*/
|
|
349
360
|
declare function ListingApp<TEntity, TFilters>(props: ListingAppProps<TFilters>): react.JSX.Element | null;
|
|
350
361
|
|
|
351
|
-
export { BottomNav as B, type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingApp as L, type MarkerRenderer as M, PaginationMode as P, StyledListingLayout as S, type IListingToolbarProps as a,
|
|
362
|
+
export { BottomNav as B, type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingApp as L, type MarkerRenderer as M, PaginationMode as P, StyledListingLayout as S, type IListingToolbarProps as a, FallbackPopup as b, type FilterControlProps as c, type FilterDefinition as d, type IListingCardProps as e, type IListingComponents as f, type IListingEmptyProps as g, type IListingFilterPanelProps as h, type IListingLoadingProps as i, type IListingMarkerProps as j, type IListingPopupProps as k, type IListingResultHeaderProps as l, type IListingSearchProps as m, type IListingSidebarProps as n, type ListingAppProps as o, ListingComponentsProvider as p, type BottomNavView as q, type IBottomNavAction as r, type IBottomNavProps as s, type IStyledListingLayoutProps as t, useListingComponents as u, type ListingAppMapProp as v };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import { b as EntityAdapter, M as MapPoint, L as LatLng, a as MapProvider } from './map-provider.interface-
|
|
3
|
+
import { b as EntityAdapter, M as MapPoint, L as LatLng, a as MapProvider } from './map-provider.interface-B5Law7gE.js';
|
|
4
4
|
|
|
5
5
|
interface FilterControlProps<TValue> {
|
|
6
6
|
value: TValue;
|
|
@@ -119,6 +119,7 @@ interface IListingComponents {
|
|
|
119
119
|
ResultHeader: ComponentType<IListingResultHeaderProps>;
|
|
120
120
|
Toolbar: ComponentType<IListingToolbarProps>;
|
|
121
121
|
}
|
|
122
|
+
declare const FallbackPopup: ComponentType<IListingPopupProps>;
|
|
122
123
|
/**
|
|
123
124
|
* Injection point for custom-component overrides. Every slot is optional —
|
|
124
125
|
* anything not provided falls back to the (unstyled) default. Mirrors
|
|
@@ -189,6 +190,8 @@ interface IStyledListingLayoutProps {
|
|
|
189
190
|
mapCenter?: LatLng;
|
|
190
191
|
/** Forwarded verbatim to `<ListingMap zoom={mapZoom} />`. */
|
|
191
192
|
mapZoom?: number;
|
|
193
|
+
/** Forwarded verbatim to `<ListingMap mapControls={mapControls} />` -- see that prop's doc comment. */
|
|
194
|
+
mapControls?: ReactNode;
|
|
192
195
|
className?: string;
|
|
193
196
|
}
|
|
194
197
|
/**
|
|
@@ -235,7 +238,7 @@ interface IStyledListingLayoutProps {
|
|
|
235
238
|
* default -- pass `autoFetch={false}`
|
|
236
239
|
* to opt out and drive the first fetch yourself.
|
|
237
240
|
*/
|
|
238
|
-
declare function StyledListingLayout({ search, toolbarEnd, mobileAction, autoFetch, hasMap: hasMapProp, mapCenter, mapZoom, className, }: IStyledListingLayoutProps): react.JSX.Element;
|
|
241
|
+
declare function StyledListingLayout({ search, toolbarEnd, mobileAction, autoFetch, hasMap: hasMapProp, mapCenter, mapZoom, mapControls, className, }: IStyledListingLayoutProps): react.JSX.Element;
|
|
239
242
|
|
|
240
243
|
/**
|
|
241
244
|
* Two-shape `map` prop: pass a ready `MapProvider`, or the `{ apiKey, mapId? }`
|
|
@@ -309,6 +312,14 @@ interface ListingAppProps<TFilters> {
|
|
|
309
312
|
mobileAction?: IBottomNavAction;
|
|
310
313
|
search?: IStyledListingLayoutProps['search'];
|
|
311
314
|
toolbarEnd?: IStyledListingLayoutProps['toolbarEnd'];
|
|
315
|
+
/**
|
|
316
|
+
* Rendered as an absolutely-positioned overlay floating over the map (e.g. zoom/fullscreen
|
|
317
|
+
* buttons) -- forwarded verbatim through `StyledListingLayout` to `ListingMap`'s own
|
|
318
|
+
* `mapControls` prop; see that prop's doc comment for the exact positioning contract. Omit
|
|
319
|
+
* (the default) to render nothing extra. Has no effect when no map is configured (the layout
|
|
320
|
+
* drops the map region entirely in that case).
|
|
321
|
+
*/
|
|
322
|
+
mapControls?: ReactNode;
|
|
312
323
|
config?: Partial<IListingConfigOptions>;
|
|
313
324
|
autoFetch?: boolean;
|
|
314
325
|
className?: string;
|
|
@@ -348,4 +359,4 @@ interface ListingAppProps<TFilters> {
|
|
|
348
359
|
*/
|
|
349
360
|
declare function ListingApp<TEntity, TFilters>(props: ListingAppProps<TFilters>): react.JSX.Element | null;
|
|
350
361
|
|
|
351
|
-
export { BottomNav as B, type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingApp as L, type MarkerRenderer as M, PaginationMode as P, StyledListingLayout as S, type IListingToolbarProps as a,
|
|
362
|
+
export { BottomNav as B, type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingApp as L, type MarkerRenderer as M, PaginationMode as P, StyledListingLayout as S, type IListingToolbarProps as a, FallbackPopup as b, type FilterControlProps as c, type FilterDefinition as d, type IListingCardProps as e, type IListingComponents as f, type IListingEmptyProps as g, type IListingFilterPanelProps as h, type IListingLoadingProps as i, type IListingMarkerProps as j, type IListingPopupProps as k, type IListingResultHeaderProps as l, type IListingSearchProps as m, type IListingSidebarProps as n, type ListingAppProps as o, ListingComponentsProvider as p, type BottomNavView as q, type IBottomNavAction as r, type IBottomNavProps as s, type IStyledListingLayoutProps as t, useListingComponents as u, type ListingAppMapProp as v };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
type EntityId = string | number;
|
|
2
|
+
interface Bounds {
|
|
3
|
+
west: number;
|
|
4
|
+
south: number;
|
|
5
|
+
east: number;
|
|
6
|
+
north: number;
|
|
7
|
+
}
|
|
8
|
+
interface LatLng {
|
|
9
|
+
lat: number;
|
|
10
|
+
lng: number;
|
|
11
|
+
}
|
|
12
|
+
interface PageRequest {
|
|
13
|
+
cursor?: string | null;
|
|
14
|
+
limit: number;
|
|
15
|
+
}
|
|
16
|
+
interface Page<T> {
|
|
17
|
+
items: T[];
|
|
18
|
+
nextCursor: string | null;
|
|
19
|
+
total?: number;
|
|
20
|
+
}
|
|
21
|
+
interface MapPoint<TEntity = unknown> {
|
|
22
|
+
id: EntityId;
|
|
23
|
+
position: LatLng;
|
|
24
|
+
entity: TEntity;
|
|
25
|
+
}
|
|
26
|
+
type QueryParams = Record<string, string | undefined>;
|
|
27
|
+
interface EntityAdapter<TEntity, TFilters> {
|
|
28
|
+
list(filters: TFilters, page: PageRequest): Promise<Page<TEntity>>;
|
|
29
|
+
getPoints(filters: TFilters, bounds: Bounds): Promise<MapPoint<TEntity>[]>;
|
|
30
|
+
getById?(id: EntityId): Promise<TEntity>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Providers that need an API key take it via their factory (e.g. `googleProvider({ apiKey })`),
|
|
35
|
+
* not per-mount.
|
|
36
|
+
*/
|
|
37
|
+
interface MapInitOptions {
|
|
38
|
+
apiKey?: string;
|
|
39
|
+
center?: LatLng;
|
|
40
|
+
zoom?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Element the Fullscreen API should target on `toggleFullscreen()`, instead of the `el`
|
|
43
|
+
* passed to `mount`. Additive/optional -- providers resolve `fullscreenTarget ?? el`, so
|
|
44
|
+
* existing callers that never supply it are unaffected.
|
|
45
|
+
*
|
|
46
|
+
* Needed because a consumer overlay rendered as a SIBLING of `el` (e.g. `ListingMap`'s
|
|
47
|
+
* `mapControls`, deliberately never a child -- a real map SDK owns `el`'s contents) would
|
|
48
|
+
* otherwise vanish the instant `el` alone is fullscreened: the Fullscreen API only shows the
|
|
49
|
+
* target element and its descendants, never its siblings. Pass an outer wrapper that contains
|
|
50
|
+
* BOTH `el` and the sibling overlay to keep the overlay visible in fullscreen.
|
|
51
|
+
*/
|
|
52
|
+
fullscreenTarget?: HTMLElement;
|
|
53
|
+
}
|
|
54
|
+
interface MapHandle {
|
|
55
|
+
readonly raw: unknown;
|
|
56
|
+
}
|
|
57
|
+
interface RenderedLayer {
|
|
58
|
+
id: string;
|
|
59
|
+
markers: Array<{
|
|
60
|
+
id: string | number;
|
|
61
|
+
position: LatLng;
|
|
62
|
+
iconUrl?: string;
|
|
63
|
+
element?: HTMLElement;
|
|
64
|
+
}>;
|
|
65
|
+
clustering?: {
|
|
66
|
+
maxZoom?: number;
|
|
67
|
+
} | false;
|
|
68
|
+
onMarkerClick?(id: string | number): void;
|
|
69
|
+
}
|
|
70
|
+
type Unsubscribe = () => void;
|
|
71
|
+
/**
|
|
72
|
+
* Handle to an imperatively-mounted, lat/lng-anchored DOM overlay (see
|
|
73
|
+
* `MapProvider.mountOverlay`). `container` is a stable element the provider
|
|
74
|
+
* created and owns positioning of -- callers portal their own content (e.g. the
|
|
75
|
+
* injected `Popup` slot) into it. `setPosition` re-anchors it at a new
|
|
76
|
+
* coordinate; `unmount` detaches it from the map and the DOM.
|
|
77
|
+
*/
|
|
78
|
+
interface MapOverlayHandle {
|
|
79
|
+
readonly container: HTMLElement;
|
|
80
|
+
setPosition(position: LatLng): void;
|
|
81
|
+
unmount(): void;
|
|
82
|
+
}
|
|
83
|
+
interface MapProvider {
|
|
84
|
+
mount(el: HTMLElement, opts: MapInitOptions): Promise<MapHandle> | MapHandle;
|
|
85
|
+
renderLayer(handle: MapHandle, layer: RenderedLayer): Unsubscribe;
|
|
86
|
+
onBoundsChange(handle: MapHandle, cb: (b: Bounds) => void): Unsubscribe;
|
|
87
|
+
/**
|
|
88
|
+
* Subscribes to clicks on the map BACKGROUND (not on a marker) and returns an
|
|
89
|
+
* unsubscribe. Used to dismiss an open on-map `Popup` overlay on a
|
|
90
|
+
* tap/click-away -- the touch-friendly counterpart to `Esc`. HTML overlay
|
|
91
|
+
* markers live in the map's `overlayMouseTarget` pane, so a marker click does
|
|
92
|
+
* NOT surface here -- only genuine background clicks do, which is exactly what
|
|
93
|
+
* dismissal wants. No `MapHandle` parameter: like `updateMarkerStates` and
|
|
94
|
+
* `mountOverlay`, a provider instance operates on its own currently-mounted map.
|
|
95
|
+
*/
|
|
96
|
+
onMapClick(cb: () => void): Unsubscribe;
|
|
97
|
+
fitBounds(handle: MapHandle, b: Bounds): void;
|
|
98
|
+
destroy(handle: MapHandle): void;
|
|
99
|
+
/**
|
|
100
|
+
* Repaints the SELECTED/HOVERED marker's existing DOM without recreating any marker -- toggles
|
|
101
|
+
* `rle-marker--selected`/`rle-marker--hovered` on each rendered marker's container node
|
|
102
|
+
* (`id === selectedId` / `id === hoveredId && id !== selectedId`, so selected wins when an id is
|
|
103
|
+
* both). No `MapHandle` parameter: a provider instance tracks its own currently-mounted map, the
|
|
104
|
+
* same way `ListingMap` holds a single `handleRef` per provider. Implementations that render
|
|
105
|
+
* markers as plain host-SDK objects with no addressable container element (e.g. this library's
|
|
106
|
+
* own advanced-marker/`AdvancedMarkerElement` mode) MAY no-op.
|
|
107
|
+
*/
|
|
108
|
+
updateMarkerStates(selectedId: EntityId | null, hoveredId: EntityId | null): void;
|
|
109
|
+
/**
|
|
110
|
+
* Mounts an absolutely-positioned DOM `container` anchored at `position` on
|
|
111
|
+
* the map (above any markers) and returns a `MapOverlayHandle` to
|
|
112
|
+
* reposition/unmount it. The `container` is created and returned
|
|
113
|
+
* SYNCHRONOUSLY so it is a stable React portal target, even though a real map
|
|
114
|
+
* SDK attaches it to a map pane and positions it ASYNCHRONOUSLY on its next
|
|
115
|
+
* render cycle (never synchronously inside the mount call) -- see the Google
|
|
116
|
+
* provider's implementation. No `MapHandle` parameter: like
|
|
117
|
+
* `updateMarkerStates`, a provider instance operates on its own
|
|
118
|
+
* currently-mounted map. Used to render the injected `Popup` slot as an
|
|
119
|
+
* on-map overlay when a point is selected.
|
|
120
|
+
*/
|
|
121
|
+
mountOverlay(position: LatLng): MapOverlayHandle;
|
|
122
|
+
/**
|
|
123
|
+
* Increments the currently-mounted map's zoom level by 1. No `MapHandle` parameter: like
|
|
124
|
+
* `updateMarkerStates`/`mountOverlay`/`onMapClick`, a provider instance operates on its own
|
|
125
|
+
* currently-mounted map. No-op (never throws) when no map is currently mounted.
|
|
126
|
+
*/
|
|
127
|
+
zoomIn(): void;
|
|
128
|
+
/** Decrements the currently-mounted map's zoom level by 1. See `zoomIn`'s doc comment. */
|
|
129
|
+
zoomOut(): void;
|
|
130
|
+
/**
|
|
131
|
+
* Toggles the browser Fullscreen API on the map's fullscreen target -- `opts.fullscreenTarget`
|
|
132
|
+
* from `mount`, falling back to the mount `el` itself when omitted (see
|
|
133
|
+
* `MapInitOptions.fullscreenTarget`'s doc comment for why a caller would supply a different
|
|
134
|
+
* element): enters fullscreen on that target if it (or a descendant) is not already the
|
|
135
|
+
* document's fullscreen element, else exits fullscreen. No `MapHandle` parameter, same
|
|
136
|
+
* rationale as `zoomIn`/`zoomOut`. Guarded against environments without the Fullscreen API
|
|
137
|
+
* (e.g. older Safari, or a test DOM that doesn't implement it) -- never throws, simply no-ops
|
|
138
|
+
* when the relevant methods aren't present. No-op when no map is currently mounted.
|
|
139
|
+
*/
|
|
140
|
+
toggleFullscreen(): void;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export type { Bounds as B, EntityId as E, LatLng as L, MapPoint as M, Page as P, QueryParams as Q, RenderedLayer as R, Unsubscribe as U, MapProvider as a, EntityAdapter as b, MapHandle as c, MapInitOptions as d, MapOverlayHandle as e, PageRequest as f };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
type EntityId = string | number;
|
|
2
|
+
interface Bounds {
|
|
3
|
+
west: number;
|
|
4
|
+
south: number;
|
|
5
|
+
east: number;
|
|
6
|
+
north: number;
|
|
7
|
+
}
|
|
8
|
+
interface LatLng {
|
|
9
|
+
lat: number;
|
|
10
|
+
lng: number;
|
|
11
|
+
}
|
|
12
|
+
interface PageRequest {
|
|
13
|
+
cursor?: string | null;
|
|
14
|
+
limit: number;
|
|
15
|
+
}
|
|
16
|
+
interface Page<T> {
|
|
17
|
+
items: T[];
|
|
18
|
+
nextCursor: string | null;
|
|
19
|
+
total?: number;
|
|
20
|
+
}
|
|
21
|
+
interface MapPoint<TEntity = unknown> {
|
|
22
|
+
id: EntityId;
|
|
23
|
+
position: LatLng;
|
|
24
|
+
entity: TEntity;
|
|
25
|
+
}
|
|
26
|
+
type QueryParams = Record<string, string | undefined>;
|
|
27
|
+
interface EntityAdapter<TEntity, TFilters> {
|
|
28
|
+
list(filters: TFilters, page: PageRequest): Promise<Page<TEntity>>;
|
|
29
|
+
getPoints(filters: TFilters, bounds: Bounds): Promise<MapPoint<TEntity>[]>;
|
|
30
|
+
getById?(id: EntityId): Promise<TEntity>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Providers that need an API key take it via their factory (e.g. `googleProvider({ apiKey })`),
|
|
35
|
+
* not per-mount.
|
|
36
|
+
*/
|
|
37
|
+
interface MapInitOptions {
|
|
38
|
+
apiKey?: string;
|
|
39
|
+
center?: LatLng;
|
|
40
|
+
zoom?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Element the Fullscreen API should target on `toggleFullscreen()`, instead of the `el`
|
|
43
|
+
* passed to `mount`. Additive/optional -- providers resolve `fullscreenTarget ?? el`, so
|
|
44
|
+
* existing callers that never supply it are unaffected.
|
|
45
|
+
*
|
|
46
|
+
* Needed because a consumer overlay rendered as a SIBLING of `el` (e.g. `ListingMap`'s
|
|
47
|
+
* `mapControls`, deliberately never a child -- a real map SDK owns `el`'s contents) would
|
|
48
|
+
* otherwise vanish the instant `el` alone is fullscreened: the Fullscreen API only shows the
|
|
49
|
+
* target element and its descendants, never its siblings. Pass an outer wrapper that contains
|
|
50
|
+
* BOTH `el` and the sibling overlay to keep the overlay visible in fullscreen.
|
|
51
|
+
*/
|
|
52
|
+
fullscreenTarget?: HTMLElement;
|
|
53
|
+
}
|
|
54
|
+
interface MapHandle {
|
|
55
|
+
readonly raw: unknown;
|
|
56
|
+
}
|
|
57
|
+
interface RenderedLayer {
|
|
58
|
+
id: string;
|
|
59
|
+
markers: Array<{
|
|
60
|
+
id: string | number;
|
|
61
|
+
position: LatLng;
|
|
62
|
+
iconUrl?: string;
|
|
63
|
+
element?: HTMLElement;
|
|
64
|
+
}>;
|
|
65
|
+
clustering?: {
|
|
66
|
+
maxZoom?: number;
|
|
67
|
+
} | false;
|
|
68
|
+
onMarkerClick?(id: string | number): void;
|
|
69
|
+
}
|
|
70
|
+
type Unsubscribe = () => void;
|
|
71
|
+
/**
|
|
72
|
+
* Handle to an imperatively-mounted, lat/lng-anchored DOM overlay (see
|
|
73
|
+
* `MapProvider.mountOverlay`). `container` is a stable element the provider
|
|
74
|
+
* created and owns positioning of -- callers portal their own content (e.g. the
|
|
75
|
+
* injected `Popup` slot) into it. `setPosition` re-anchors it at a new
|
|
76
|
+
* coordinate; `unmount` detaches it from the map and the DOM.
|
|
77
|
+
*/
|
|
78
|
+
interface MapOverlayHandle {
|
|
79
|
+
readonly container: HTMLElement;
|
|
80
|
+
setPosition(position: LatLng): void;
|
|
81
|
+
unmount(): void;
|
|
82
|
+
}
|
|
83
|
+
interface MapProvider {
|
|
84
|
+
mount(el: HTMLElement, opts: MapInitOptions): Promise<MapHandle> | MapHandle;
|
|
85
|
+
renderLayer(handle: MapHandle, layer: RenderedLayer): Unsubscribe;
|
|
86
|
+
onBoundsChange(handle: MapHandle, cb: (b: Bounds) => void): Unsubscribe;
|
|
87
|
+
/**
|
|
88
|
+
* Subscribes to clicks on the map BACKGROUND (not on a marker) and returns an
|
|
89
|
+
* unsubscribe. Used to dismiss an open on-map `Popup` overlay on a
|
|
90
|
+
* tap/click-away -- the touch-friendly counterpart to `Esc`. HTML overlay
|
|
91
|
+
* markers live in the map's `overlayMouseTarget` pane, so a marker click does
|
|
92
|
+
* NOT surface here -- only genuine background clicks do, which is exactly what
|
|
93
|
+
* dismissal wants. No `MapHandle` parameter: like `updateMarkerStates` and
|
|
94
|
+
* `mountOverlay`, a provider instance operates on its own currently-mounted map.
|
|
95
|
+
*/
|
|
96
|
+
onMapClick(cb: () => void): Unsubscribe;
|
|
97
|
+
fitBounds(handle: MapHandle, b: Bounds): void;
|
|
98
|
+
destroy(handle: MapHandle): void;
|
|
99
|
+
/**
|
|
100
|
+
* Repaints the SELECTED/HOVERED marker's existing DOM without recreating any marker -- toggles
|
|
101
|
+
* `rle-marker--selected`/`rle-marker--hovered` on each rendered marker's container node
|
|
102
|
+
* (`id === selectedId` / `id === hoveredId && id !== selectedId`, so selected wins when an id is
|
|
103
|
+
* both). No `MapHandle` parameter: a provider instance tracks its own currently-mounted map, the
|
|
104
|
+
* same way `ListingMap` holds a single `handleRef` per provider. Implementations that render
|
|
105
|
+
* markers as plain host-SDK objects with no addressable container element (e.g. this library's
|
|
106
|
+
* own advanced-marker/`AdvancedMarkerElement` mode) MAY no-op.
|
|
107
|
+
*/
|
|
108
|
+
updateMarkerStates(selectedId: EntityId | null, hoveredId: EntityId | null): void;
|
|
109
|
+
/**
|
|
110
|
+
* Mounts an absolutely-positioned DOM `container` anchored at `position` on
|
|
111
|
+
* the map (above any markers) and returns a `MapOverlayHandle` to
|
|
112
|
+
* reposition/unmount it. The `container` is created and returned
|
|
113
|
+
* SYNCHRONOUSLY so it is a stable React portal target, even though a real map
|
|
114
|
+
* SDK attaches it to a map pane and positions it ASYNCHRONOUSLY on its next
|
|
115
|
+
* render cycle (never synchronously inside the mount call) -- see the Google
|
|
116
|
+
* provider's implementation. No `MapHandle` parameter: like
|
|
117
|
+
* `updateMarkerStates`, a provider instance operates on its own
|
|
118
|
+
* currently-mounted map. Used to render the injected `Popup` slot as an
|
|
119
|
+
* on-map overlay when a point is selected.
|
|
120
|
+
*/
|
|
121
|
+
mountOverlay(position: LatLng): MapOverlayHandle;
|
|
122
|
+
/**
|
|
123
|
+
* Increments the currently-mounted map's zoom level by 1. No `MapHandle` parameter: like
|
|
124
|
+
* `updateMarkerStates`/`mountOverlay`/`onMapClick`, a provider instance operates on its own
|
|
125
|
+
* currently-mounted map. No-op (never throws) when no map is currently mounted.
|
|
126
|
+
*/
|
|
127
|
+
zoomIn(): void;
|
|
128
|
+
/** Decrements the currently-mounted map's zoom level by 1. See `zoomIn`'s doc comment. */
|
|
129
|
+
zoomOut(): void;
|
|
130
|
+
/**
|
|
131
|
+
* Toggles the browser Fullscreen API on the map's fullscreen target -- `opts.fullscreenTarget`
|
|
132
|
+
* from `mount`, falling back to the mount `el` itself when omitted (see
|
|
133
|
+
* `MapInitOptions.fullscreenTarget`'s doc comment for why a caller would supply a different
|
|
134
|
+
* element): enters fullscreen on that target if it (or a descendant) is not already the
|
|
135
|
+
* document's fullscreen element, else exits fullscreen. No `MapHandle` parameter, same
|
|
136
|
+
* rationale as `zoomIn`/`zoomOut`. Guarded against environments without the Fullscreen API
|
|
137
|
+
* (e.g. older Safari, or a test DOM that doesn't implement it) -- never throws, simply no-ops
|
|
138
|
+
* when the relevant methods aren't present. No-op when no map is currently mounted.
|
|
139
|
+
*/
|
|
140
|
+
toggleFullscreen(): void;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export type { Bounds as B, EntityId as E, LatLng as L, MapPoint as M, Page as P, QueryParams as Q, RenderedLayer as R, Unsubscribe as U, MapProvider as a, EntityAdapter as b, MapHandle as c, MapInitOptions as d, MapOverlayHandle as e, PageRequest as f };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
|
-
var _jsapiloader = require('@googlemaps/js-api-loader');var
|
|
2
|
+
var _jsapiloader = require('@googlemaps/js-api-loader');var P="DEMO_MAP_ID";function p(r){return r.raw}function H(r,n){if(r.element)return r.element;if(r.iconUrl)return new n.PinElement({glyphSrc:r.iconUrl}).element}var L=12,R="#b3261e";function I(r){if(r.element)return r.element;if(r.iconUrl){let i=document.createElement("img");return i.src=r.iconUrl,i}let n=document.createElement("div");return n.style.width=`${L}px`,n.style.height=`${L}px`,n.style.borderRadius="50%",n.style.backgroundColor=R,n.style.border="2px solid #ffffff",n.style.boxShadow="0 1px 4px rgba(0, 0, 0, 0.4)",n}var m;function x(){if(m)return m;class r extends google.maps.OverlayView{constructor(t,s,a,e){super();r.prototype.__init.call(this);;this.position=t;this.content=s;this.onClick=a;this.lifecycle=e}__init() {this.div=null}onAdd(){let t=document.createElement("div");t.style.position="absolute",t.style.transform="translate(-50%, -50%)",this.onClick&&(t.style.cursor="pointer",t.addEventListener("click",this.onClick)),t.appendChild(this.content),this.div=t,_optionalChain([this, 'access', _2 => _2.getPanes, 'call', _3 => _3(), 'optionalAccess', _4 => _4.overlayMouseTarget, 'access', _5 => _5.appendChild, 'call', _6 => _6(t)]),this.lifecycle.onContainerAdd(t)}draw(){if(!this.div)return;let t=this.getProjection();if(!t)return;let s=t.fromLatLngToDivPixel(new google.maps.LatLng(this.position.lat,this.position.lng));s&&(this.div.style.left=`${s.x}px`,this.div.style.top=`${s.y}px`)}onRemove(){let t=this.div;_optionalChain([this, 'access', _7 => _7.div, 'optionalAccess', _8 => _8.remove, 'call', _9 => _9()]),this.div=null,t&&this.lifecycle.onContainerRemove(t)}}return m=r,m}var A=14,f;function T(){if(f)return f;class r extends google.maps.OverlayView{constructor(t,s){super();r.prototype.__init2.call(this);;this.container=t;this.position=s}__init2() {this.attached=!1}onAdd(){this.attached=!0,_optionalChain([this, 'access', _10 => _10.getPanes, 'call', _11 => _11(), 'optionalAccess', _12 => _12.floatPane, 'access', _13 => _13.appendChild, 'call', _14 => _14(this.container)])}draw(){let t=this.getProjection();if(!t)return;let s=t.fromLatLngToDivPixel(new google.maps.LatLng(this.position.lat,this.position.lng));s&&(this.container.style.left=`${s.x}px`,this.container.style.top=`${s.y-A}px`)}onRemove(){this.attached=!1,this.container.remove()}updatePosition(t){this.position=t,this.attached&&this.draw()}}return f=r,f}function g(r){for(let n of r)typeof n.setMap=="function"?n.setMap(null):n.map=null}var S="#b3261e",G=40,_=64,z=14;function U(r,n){let i=n.count,t=Math.min(_,G+Math.round(Math.log10(i+1)*z)),s=document.createElement("div");return s.textContent=String(i),s.style.display="flex",s.style.alignItems="center",s.style.justifyContent="center",s.style.width=`${t}px`,s.style.height=`${t}px`,s.style.borderRadius="50%",s.style.backgroundColor=S,s.style.border="2px solid #ffffff",s.style.boxShadow="0 1px 4px rgba(0, 0, 0, 0.4)",s.style.color="#ffffff",s.style.fontFamily="inherit",s.style.fontWeight="700",s.style.fontSize=t>=52?"15px":"13px",new r.AdvancedMarkerElement({position:n.position,content:s})}var E=!1;async function F(r,n,i,t){let s;try{s=await Promise.resolve().then(() => _interopRequireWildcard(require("@googlemaps/markerclusterer")))}catch(e){E||(E=!0,console.warn('[react-listing-engine] "@googlemaps/markerclusterer" is not installed -- rendering plain (unclustered) markers instead. Install "@googlemaps/markerclusterer" to enable clustering.',e));return}if(r.layers.get(n)!==i)return;let a=new s.MarkerClusterer({map:r.map,markers:i,algorithmOptions:{maxZoom:t.maxZoom},renderer:{render:e=>U(r.markerLib,e)}});r.clusterers.set(n,a)}function v(r,n){let i=r.clusterers.get(n);i&&(i.setMap(null),r.clusterers.delete(n))}var h=!1;function B(){h||(h=!0,console.warn('[react-listing-engine] Marker clustering is not supported in `styles` (OverlayView) mode -- "@googlemaps/markerclusterer" only manages Marker/AdvancedMarkerElement instances. Rendering plain, unclustered overlay markers instead. Use a `mapId` (advanced-marker mode) to enable clustering.'))}function Z(r,n){return n.markers.map(i=>{let t=new r.markerLib.AdvancedMarkerElement({map:r.map,position:i.position,content:H(i,r.markerLib),gmpClickable:!!n.onMarkerClick});if(n.onMarkerClick){let s=n.onMarkerClick;t.addListener("click",()=>s(i.id))}return t})}function b(r,n,i,t){r.classList.toggle("rle-marker--selected",n===i),r.classList.toggle("rle-marker--hovered",n===t&&n!==i)}function D(r,n){let i=x();return n.markers.map(t=>{let s=n.onMarkerClick,a=s?()=>s(t.id):void 0,e=new i(t.position,I(t),a,{onContainerAdd:o=>{r.markerElements.set(t.id,o),b(o,t.id,r.selectedMarkerId,r.hoveredMarkerId)},onContainerRemove:o=>{r.markerElements.get(t.id)===o&&r.markerElements.delete(t.id)}});return e.setMap(r.map),e})}function C(r,n){let i=r.layerMarkerIds.get(n);if(i){for(let t of i)r.markerElements.delete(t);r.layerMarkerIds.delete(n)}}function V(r){let n=r.getSouthWest(),i=r.getNorthEast();return{west:n.lng(),south:n.lat(),east:i.lng(),north:i.lat()}}function $(r,n,i){if(typeof ResizeObserver>"u")return;let t=!1,s=()=>{let{width:e,height:o}=r.getBoundingClientRect();e===0||o===0||(google.maps.event.trigger(n,"resize"),t||(t=!0,n.setCenter(i)))},a=new ResizeObserver(s);return a.observe(r),typeof requestAnimationFrame<"u"?requestAnimationFrame(s):queueMicrotask(s),a}function q(r){if(!r.apiKey)throw new Error("googleProvider: config.apiKey is required (no hardcoded fallback key is ever used).");let n=!1,i=()=>{n||(_jsapiloader.setOptions.call(void 0, {...r.loaderOptions,key:r.apiKey}),n=!0)},t,s=0;return{async mount(a,e){let o=++s;i();let l=await _jsapiloader.importLibrary.call(void 0, "maps"),d=await _jsapiloader.importLibrary.call(void 0, "marker"),c=_nullishCoalesce(e.center, () => ({lat:0,lng:0})),u=r.styles!=null,M=new l.Map(a,{...r.mapOptions,center:c,zoom:_nullishCoalesce(e.zoom, () => (10)),...u?{styles:r.styles}:{mapId:_nullishCoalesce(r.mapId, () => (P))}}),O=$(a,M,c),y={map:M,containerEl:a,fullscreenEl:_nullishCoalesce(e.fullscreenTarget, () => (a)),markerLib:d,markerMode:u?"overlay":"advanced",layers:new Map,clusterers:new Map,boundsListeners:new Set,clickListeners:new Set,resizeObserver:O,markerElements:new Map,layerMarkerIds:new Map,selectedMarkerId:null,hoveredMarkerId:null};return o===s&&(t=y),{raw:y}},renderLayer(a,e){let o=p(a),l=o.layers.get(e.id);l&&(g(l),o.layers.delete(e.id),C(o,e.id)),v(o,e.id);let d=o.markerMode==="overlay"?D(o,e):Z(o,e);o.layers.set(e.id,d),o.markerMode==="overlay"&&o.layerMarkerIds.set(e.id,e.markers.map(u=>u.id)),e.clustering&&(o.markerMode==="overlay"?B():F(o,e.id,d,e.clustering));let c=!1;return()=>{c||(c=!0,o.layers.get(e.id)===d&&(g(d),o.layers.delete(e.id),v(o,e.id),C(o,e.id)))}},onBoundsChange(a,e){let o=p(a),l=o.map.addListener("idle",()=>{let c=o.map.getBounds();c&&e(V(c))});o.boundsListeners.add(l);let d=!1;return()=>{d||(d=!0,l.remove(),o.boundsListeners.delete(l))}},onMapClick(a){let e=t;if(!e)return()=>{};let o=e.map.addListener("click",()=>a());e.clickListeners.add(o);let l=!1;return()=>{l||(l=!0,o.remove(),e.clickListeners.delete(o))}},fitBounds(a,e){p(a).map.fitBounds(e)},destroy(a){let e=p(a);_optionalChain([e, 'access', _15 => _15.resizeObserver, 'optionalAccess', _16 => _16.disconnect, 'call', _17 => _17()]);for(let o of e.boundsListeners)o.remove();e.boundsListeners.clear();for(let o of e.clickListeners)o.remove();e.clickListeners.clear();for(let o of[...e.clusterers.keys()])v(e,o);for(let o of e.layers.values())g(o);e.layers.clear(),e.markerElements.clear(),e.layerMarkerIds.clear(),t===e&&(t=void 0)},updateMarkerStates(a,e){if(t){t.selectedMarkerId=a,t.hoveredMarkerId=e;for(let[o,l]of t.markerElements)b(l,o,a,e)}},mountOverlay(a){let e=document.createElement("div");if(e.style.position="absolute",e.style.transform="translate(-50%, -100%)",e.style.pointerEvents="auto",!t)return{container:e,setPosition:()=>{},unmount:()=>e.remove()};let o=T(),l=new o(e,a);return l.setMap(t.map),{container:e,setPosition:d=>l.updatePosition(d),unmount:()=>{l.setMap(null),e.remove()}}},zoomIn(){t&&t.map.setZoom((_nullishCoalesce(t.map.getZoom(), () => (0)))+1)},zoomOut(){t&&t.map.setZoom((_nullishCoalesce(t.map.getZoom(), () => (0)))-1)},toggleFullscreen(){if(!t)return;let a=t.fullscreenEl,e=document.fullscreenElement;e!=null&&a.contains(e)?typeof document.exitFullscreen=="function"&&_optionalChain([document, 'access', _18 => _18.exitFullscreen, 'call', _19 => _19(), 'optionalAccess', _20 => _20.catch, 'call', _21 => _21(()=>{})]):typeof a.requestFullscreen=="function"&&_optionalChain([a, 'access', _22 => _22.requestFullscreen, 'call', _23 => _23(), 'optionalAccess', _24 => _24.catch, 'call', _25 => _25(()=>{})])}}}exports.googleProvider = q;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIOptions } from '@googlemaps/js-api-loader';
|
|
2
|
-
import { a as MapProvider } from '../../map-provider.interface-
|
|
2
|
+
import { a as MapProvider } from '../../map-provider.interface-B5Law7gE.cjs';
|
|
3
3
|
|
|
4
4
|
interface GoogleMapsProviderConfig {
|
|
5
5
|
/** Google Maps JavaScript API key. Required -- there is no hardcoded fallback. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIOptions } from '@googlemaps/js-api-loader';
|
|
2
|
-
import { a as MapProvider } from '../../map-provider.interface-
|
|
2
|
+
import { a as MapProvider } from '../../map-provider.interface-B5Law7gE.js';
|
|
3
3
|
|
|
4
4
|
interface GoogleMapsProviderConfig {
|
|
5
5
|
/** Google Maps JavaScript API key. Required -- there is no hardcoded fallback. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{importLibrary as
|
|
2
|
+
import{importLibrary as k,setOptions as w}from"@googlemaps/js-api-loader";var P="DEMO_MAP_ID";function p(r){return r.raw}function H(r,n){if(r.element)return r.element;if(r.iconUrl)return new n.PinElement({glyphSrc:r.iconUrl}).element}var L=12,R="#b3261e";function I(r){if(r.element)return r.element;if(r.iconUrl){let i=document.createElement("img");return i.src=r.iconUrl,i}let n=document.createElement("div");return n.style.width=`${L}px`,n.style.height=`${L}px`,n.style.borderRadius="50%",n.style.backgroundColor=R,n.style.border="2px solid #ffffff",n.style.boxShadow="0 1px 4px rgba(0, 0, 0, 0.4)",n}var m;function x(){if(m)return m;class r extends google.maps.OverlayView{constructor(t,s,a,e){super();this.position=t;this.content=s;this.onClick=a;this.lifecycle=e}position;content;onClick;lifecycle;div=null;onAdd(){let t=document.createElement("div");t.style.position="absolute",t.style.transform="translate(-50%, -50%)",this.onClick&&(t.style.cursor="pointer",t.addEventListener("click",this.onClick)),t.appendChild(this.content),this.div=t,this.getPanes()?.overlayMouseTarget.appendChild(t),this.lifecycle.onContainerAdd(t)}draw(){if(!this.div)return;let t=this.getProjection();if(!t)return;let s=t.fromLatLngToDivPixel(new google.maps.LatLng(this.position.lat,this.position.lng));s&&(this.div.style.left=`${s.x}px`,this.div.style.top=`${s.y}px`)}onRemove(){let t=this.div;this.div?.remove(),this.div=null,t&&this.lifecycle.onContainerRemove(t)}}return m=r,m}var A=14,f;function T(){if(f)return f;class r extends google.maps.OverlayView{constructor(t,s){super();this.container=t;this.position=s}container;position;attached=!1;onAdd(){this.attached=!0,this.getPanes()?.floatPane.appendChild(this.container)}draw(){let t=this.getProjection();if(!t)return;let s=t.fromLatLngToDivPixel(new google.maps.LatLng(this.position.lat,this.position.lng));s&&(this.container.style.left=`${s.x}px`,this.container.style.top=`${s.y-A}px`)}onRemove(){this.attached=!1,this.container.remove()}updatePosition(t){this.position=t,this.attached&&this.draw()}}return f=r,f}function g(r){for(let n of r)typeof n.setMap=="function"?n.setMap(null):n.map=null}var S="#b3261e",G=40,_=64,z=14;function U(r,n){let i=n.count,t=Math.min(_,G+Math.round(Math.log10(i+1)*z)),s=document.createElement("div");return s.textContent=String(i),s.style.display="flex",s.style.alignItems="center",s.style.justifyContent="center",s.style.width=`${t}px`,s.style.height=`${t}px`,s.style.borderRadius="50%",s.style.backgroundColor=S,s.style.border="2px solid #ffffff",s.style.boxShadow="0 1px 4px rgba(0, 0, 0, 0.4)",s.style.color="#ffffff",s.style.fontFamily="inherit",s.style.fontWeight="700",s.style.fontSize=t>=52?"15px":"13px",new r.AdvancedMarkerElement({position:n.position,content:s})}var E=!1;async function F(r,n,i,t){let s;try{s=await import("@googlemaps/markerclusterer")}catch(e){E||(E=!0,console.warn('[react-listing-engine] "@googlemaps/markerclusterer" is not installed -- rendering plain (unclustered) markers instead. Install "@googlemaps/markerclusterer" to enable clustering.',e));return}if(r.layers.get(n)!==i)return;let a=new s.MarkerClusterer({map:r.map,markers:i,algorithmOptions:{maxZoom:t.maxZoom},renderer:{render:e=>U(r.markerLib,e)}});r.clusterers.set(n,a)}function v(r,n){let i=r.clusterers.get(n);i&&(i.setMap(null),r.clusterers.delete(n))}var h=!1;function B(){h||(h=!0,console.warn('[react-listing-engine] Marker clustering is not supported in `styles` (OverlayView) mode -- "@googlemaps/markerclusterer" only manages Marker/AdvancedMarkerElement instances. Rendering plain, unclustered overlay markers instead. Use a `mapId` (advanced-marker mode) to enable clustering.'))}function Z(r,n){return n.markers.map(i=>{let t=new r.markerLib.AdvancedMarkerElement({map:r.map,position:i.position,content:H(i,r.markerLib),gmpClickable:!!n.onMarkerClick});if(n.onMarkerClick){let s=n.onMarkerClick;t.addListener("click",()=>s(i.id))}return t})}function b(r,n,i,t){r.classList.toggle("rle-marker--selected",n===i),r.classList.toggle("rle-marker--hovered",n===t&&n!==i)}function D(r,n){let i=x();return n.markers.map(t=>{let s=n.onMarkerClick,a=s?()=>s(t.id):void 0,e=new i(t.position,I(t),a,{onContainerAdd:o=>{r.markerElements.set(t.id,o),b(o,t.id,r.selectedMarkerId,r.hoveredMarkerId)},onContainerRemove:o=>{r.markerElements.get(t.id)===o&&r.markerElements.delete(t.id)}});return e.setMap(r.map),e})}function C(r,n){let i=r.layerMarkerIds.get(n);if(i){for(let t of i)r.markerElements.delete(t);r.layerMarkerIds.delete(n)}}function V(r){let n=r.getSouthWest(),i=r.getNorthEast();return{west:n.lng(),south:n.lat(),east:i.lng(),north:i.lat()}}function $(r,n,i){if(typeof ResizeObserver>"u")return;let t=!1,s=()=>{let{width:e,height:o}=r.getBoundingClientRect();e===0||o===0||(google.maps.event.trigger(n,"resize"),t||(t=!0,n.setCenter(i)))},a=new ResizeObserver(s);return a.observe(r),typeof requestAnimationFrame<"u"?requestAnimationFrame(s):queueMicrotask(s),a}function q(r){if(!r.apiKey)throw new Error("googleProvider: config.apiKey is required (no hardcoded fallback key is ever used).");let n=!1,i=()=>{n||(w({...r.loaderOptions,key:r.apiKey}),n=!0)},t,s=0;return{async mount(a,e){let o=++s;i();let l=await k("maps"),d=await k("marker"),c=e.center??{lat:0,lng:0},u=r.styles!=null,M=new l.Map(a,{...r.mapOptions,center:c,zoom:e.zoom??10,...u?{styles:r.styles}:{mapId:r.mapId??P}}),O=$(a,M,c),y={map:M,containerEl:a,fullscreenEl:e.fullscreenTarget??a,markerLib:d,markerMode:u?"overlay":"advanced",layers:new Map,clusterers:new Map,boundsListeners:new Set,clickListeners:new Set,resizeObserver:O,markerElements:new Map,layerMarkerIds:new Map,selectedMarkerId:null,hoveredMarkerId:null};return o===s&&(t=y),{raw:y}},renderLayer(a,e){let o=p(a),l=o.layers.get(e.id);l&&(g(l),o.layers.delete(e.id),C(o,e.id)),v(o,e.id);let d=o.markerMode==="overlay"?D(o,e):Z(o,e);o.layers.set(e.id,d),o.markerMode==="overlay"&&o.layerMarkerIds.set(e.id,e.markers.map(u=>u.id)),e.clustering&&(o.markerMode==="overlay"?B():F(o,e.id,d,e.clustering));let c=!1;return()=>{c||(c=!0,o.layers.get(e.id)===d&&(g(d),o.layers.delete(e.id),v(o,e.id),C(o,e.id)))}},onBoundsChange(a,e){let o=p(a),l=o.map.addListener("idle",()=>{let c=o.map.getBounds();c&&e(V(c))});o.boundsListeners.add(l);let d=!1;return()=>{d||(d=!0,l.remove(),o.boundsListeners.delete(l))}},onMapClick(a){let e=t;if(!e)return()=>{};let o=e.map.addListener("click",()=>a());e.clickListeners.add(o);let l=!1;return()=>{l||(l=!0,o.remove(),e.clickListeners.delete(o))}},fitBounds(a,e){p(a).map.fitBounds(e)},destroy(a){let e=p(a);e.resizeObserver?.disconnect();for(let o of e.boundsListeners)o.remove();e.boundsListeners.clear();for(let o of e.clickListeners)o.remove();e.clickListeners.clear();for(let o of[...e.clusterers.keys()])v(e,o);for(let o of e.layers.values())g(o);e.layers.clear(),e.markerElements.clear(),e.layerMarkerIds.clear(),t===e&&(t=void 0)},updateMarkerStates(a,e){if(t){t.selectedMarkerId=a,t.hoveredMarkerId=e;for(let[o,l]of t.markerElements)b(l,o,a,e)}},mountOverlay(a){let e=document.createElement("div");if(e.style.position="absolute",e.style.transform="translate(-50%, -100%)",e.style.pointerEvents="auto",!t)return{container:e,setPosition:()=>{},unmount:()=>e.remove()};let o=T(),l=new o(e,a);return l.setMap(t.map),{container:e,setPosition:d=>l.updatePosition(d),unmount:()=>{l.setMap(null),e.remove()}}},zoomIn(){t&&t.map.setZoom((t.map.getZoom()??0)+1)},zoomOut(){t&&t.map.setZoom((t.map.getZoom()??0)-1)},toggleFullscreen(){if(!t)return;let a=t.fullscreenEl,e=document.fullscreenElement;e!=null&&a.contains(e)?typeof document.exitFullscreen=="function"&&document.exitFullscreen()?.catch(()=>{}):typeof a.requestFullscreen=="function"&&a.requestFullscreen()?.catch(()=>{})}}}export{q as googleProvider};
|
package/dist/styled/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
-
var
|
|
2
|
+
var _chunk3O6X563Hcjs = require('../chunk-3O6X563H.cjs');var _jsxruntime = require('react/jsx-runtime');function L({children:o}){return _jsxruntime.jsx.call(void 0, _chunk3O6X563Hcjs.q,{..._chunk3O6X563Hcjs.O,children:o})}exports.BottomNav = _chunk3O6X563Hcjs.P; exports.BottomSheet = _chunk3O6X563Hcjs.Q; exports.ListingApp = _chunk3O6X563Hcjs.S; exports.StyledCard = _chunk3O6X563Hcjs.E; exports.StyledComponentsProviderWithDefaults = L; exports.StyledEmpty = _chunk3O6X563Hcjs.F; exports.StyledFilterPanel = _chunk3O6X563Hcjs.G; exports.StyledListingLayout = _chunk3O6X563Hcjs.R; exports.StyledLoading = _chunk3O6X563Hcjs.H; exports.StyledMarker = _chunk3O6X563Hcjs.I; exports.StyledPopup = _chunk3O6X563Hcjs.J; exports.StyledResultHeader = _chunk3O6X563Hcjs.K; exports.StyledSearch = _chunk3O6X563Hcjs.L; exports.StyledSidebar = _chunk3O6X563Hcjs.M; exports.StyledToolbar = _chunk3O6X563Hcjs.N; exports.styledDefaultComponents = _chunk3O6X563Hcjs.O;
|
package/dist/styled/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { B as BottomNav,
|
|
5
|
-
import '../map-provider.interface-
|
|
3
|
+
import { e as IListingCardProps, g as IListingEmptyProps, h as IListingFilterPanelProps, i as IListingLoadingProps, j as IListingMarkerProps, k as IListingPopupProps, l as IListingResultHeaderProps, m as IListingSearchProps, n as IListingSidebarProps, a as IListingToolbarProps, f as IListingComponents } from '../listing-app-C7EeHlmP.cjs';
|
|
4
|
+
export { B as BottomNav, q as BottomNavView, r as IBottomNavAction, s as IBottomNavProps, t as IStyledListingLayoutProps, L as ListingApp, v as ListingAppMapProp, o as ListingAppProps, S as StyledListingLayout } from '../listing-app-C7EeHlmP.cjs';
|
|
5
|
+
import '../map-provider.interface-B5Law7gE.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Default `/styled` `Card` slot. Renders an optional image, title, subtitle,
|
package/dist/styled/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { B as BottomNav,
|
|
5
|
-
import '../map-provider.interface-
|
|
3
|
+
import { e as IListingCardProps, g as IListingEmptyProps, h as IListingFilterPanelProps, i as IListingLoadingProps, j as IListingMarkerProps, k as IListingPopupProps, l as IListingResultHeaderProps, m as IListingSearchProps, n as IListingSidebarProps, a as IListingToolbarProps, f as IListingComponents } from '../listing-app-DHFJtnKI.js';
|
|
4
|
+
export { B as BottomNav, q as BottomNavView, r as IBottomNavAction, s as IBottomNavProps, t as IStyledListingLayoutProps, L as ListingApp, v as ListingAppMapProp, o as ListingAppProps, S as StyledListingLayout } from '../listing-app-DHFJtnKI.js';
|
|
5
|
+
import '../map-provider.interface-B5Law7gE.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Default `/styled` `Card` slot. Renders an optional image, title, subtitle,
|
package/dist/styled/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{
|
|
2
|
+
import{E as r,F as p,G as i,H as d,I as y,J as l,K as n,L as m,M as s,N as a,O as t,P as S,Q as f,R as P,S as u,q as e}from"../chunk-SIMKBYC6.js";import{jsx as g}from"react/jsx-runtime";function L({children:o}){return g(e,{...t,children:o})}export{S as BottomNav,f as BottomSheet,u as ListingApp,r as StyledCard,L as StyledComponentsProviderWithDefaults,p as StyledEmpty,i as StyledFilterPanel,P as StyledListingLayout,d as StyledLoading,y as StyledMarker,l as StyledPopup,n as StyledResultHeader,m as StyledSearch,s as StyledSidebar,a as StyledToolbar,t as styledDefaultComponents};
|
package/dist/testing/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); var _class;"use client";
|
|
2
|
-
var o= (_class =class{constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this); }__init() {this.mounts=[]}__init2() {this.renderedLayers=[]}__init3() {this.removedLayers=[]}__init4() {this.fitBoundsCalls=[]}__init5() {this.destroyed=[]}__init6() {this.destroyCount=0}__init7() {this.boundsListeners=new Set}mount(t,e){let n={raw:{el:t,opts:e}};return this.mounts.push(n),n}renderLayer(t,e){this.renderedLayers.push(e);let n=!1;return()=>{if(n)return;n=!0;let s=this.renderedLayers.indexOf(e);s!==-1&&(this.renderedLayers.splice(s,1),this.removedLayers.push(e))}}onBoundsChange(t,e){return this.boundsListeners.add(e),()=>{this.boundsListeners.delete(e)}}emitBounds(t){for(let e of this.boundsListeners)e(t)}fitBounds(t,e){this.fitBoundsCalls.push(e)}destroy(t){this.destroyed.push(t),this.destroyCount+=1,this.boundsListeners.clear()}}, _class);var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;"use client";
|
|
2
|
+
var o= (_class =class{constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this); }__init() {this.mounts=[]}__init2() {this.renderedLayers=[]}__init3() {this.removedLayers=[]}__init4() {this.fitBoundsCalls=[]}__init5() {this.destroyed=[]}__init6() {this.destroyCount=0}__init7() {this.markerStates=null}__init8() {this.overlays=[]}__init9() {this.zoomCalls=[]}__init10() {this.fullscreenToggles=0}__init11() {this.boundsListeners=new Set}__init12() {this.mapClickListeners=new Set}mount(t,e){let n={raw:{el:t,opts:e}};return this.mounts.push(n),this.fullscreenTarget=_nullishCoalesce(e.fullscreenTarget, () => (t)),n}renderLayer(t,e){this.renderedLayers.push(e);let n=!1;return()=>{if(n)return;n=!0;let s=this.renderedLayers.indexOf(e);s!==-1&&(this.renderedLayers.splice(s,1),this.removedLayers.push(e))}}onBoundsChange(t,e){return this.boundsListeners.add(e),()=>{this.boundsListeners.delete(e)}}emitBounds(t){for(let e of this.boundsListeners)e(t)}onMapClick(t){return this.mapClickListeners.add(t),()=>{this.mapClickListeners.delete(t)}}emitMapClick(){for(let t of this.mapClickListeners)t()}fitBounds(t,e){this.fitBoundsCalls.push(e)}destroy(t){this.destroyed.push(t),this.destroyCount+=1,this.boundsListeners.clear(),this.mapClickListeners.clear()}updateMarkerStates(t,e){this.markerStates={selected:t,hovered:e}}mountOverlay(t){let e=document.createElement("div");document.body.appendChild(e);let n={container:e,position:t};return this.overlays.push(n),{container:e,setPosition:s=>{n.position=s},unmount:()=>{e.remove();let s=this.overlays.indexOf(n);s!==-1&&this.overlays.splice(s,1)}}}zoomIn(){this.zoomCalls.push("in")}zoomOut(){this.zoomCalls.push("out")}toggleFullscreen(){this.fullscreenToggles+=1,this.fullscreenTarget&&typeof this.fullscreenTarget.requestFullscreen=="function"&&_optionalChain([this, 'access', _ => _.fullscreenTarget, 'access', _2 => _2.requestFullscreen, 'call', _3 => _3(), 'optionalAccess', _4 => _4.catch, 'call', _5 => _5(()=>{})])}}, _class);var a=class{constructor(t,e,n,s=r=>r.id){this.rows=t;this.predicate=e;this.toLatLng=n;this.idOf=s}async list(t,e){let n=this.rows.filter(u=>this.predicate(u,t)),s=e.cursor==null?0:Number(e.cursor)+1,r=n.slice(s,s+e.limit),i=s+r.length-1,l=i+1<n.length;return{items:r,nextCursor:l?String(i):null,total:n.length}}async getPoints(t,e){let s=this.rows.filter(r=>this.predicate(r,t)).map(r=>({id:this.idOf(r),position:this.toLatLng(r),entity:r}));return e?s.filter(r=>this.isInBounds(r.position,e)):s}async getById(t){let e=this.rows.find(n=>this.idOf(n)===t);if(!e)throw new Error(`InMemoryEntityAdapter: no row with id "${String(t)}"`);return e}isInBounds(t,e){return t.lat<=e.north&&t.lat>=e.south&&t.lng>=e.west&&t.lng<=e.east}};exports.FakeMapProvider = o; exports.InMemoryEntityAdapter = a;
|