react-listing-engine 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -40
- package/dist/{components-provider-CjMxkxrP.d.ts → components-provider-FinfaqUT.d.cts} +13 -2
- package/dist/{components-provider-CF0Mo0B8.d.cts → components-provider-cWVWEDXC.d.ts} +13 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +7 -10
- package/dist/index.d.ts +7 -10
- package/dist/index.js +1 -1
- package/dist/{listing-app-wmMuDlVU.d.ts → listing-app-BMoMKD4c.d.cts} +3 -5
- package/dist/{listing-app-DJbvx3oe.d.cts → listing-app-BSJKGh7k.d.ts} +3 -5
- package/dist/map-provider.interface-DT-v1plm.d.cts +67 -0
- package/dist/map-provider.interface-DT-v1plm.d.ts +67 -0
- package/dist/maps/google/index.d.cts +1 -2
- package/dist/maps/google/index.d.ts +1 -2
- package/dist/shadcn/index.cjs +1 -1
- package/dist/shadcn/index.d.cts +5 -7
- package/dist/shadcn/index.d.ts +5 -7
- package/dist/shadcn/index.js +1 -1
- package/dist/styled/index.d.cts +3 -5
- package/dist/styled/index.d.ts +3 -5
- package/dist/testing/index.d.cts +1 -2
- package/dist/testing/index.d.ts +1 -2
- package/dist/{url-sync.controller-DX67JivW.d.ts → url-sync.controller-DK5W_0OZ.d.ts} +1 -1
- package/dist/{url-sync.controller-CsU_QxoS.d.cts → url-sync.controller-DXSIWgTa.d.cts} +1 -1
- package/package.json +1 -6
- package/dist/chunk-5FBI2WIM.js +0 -2
- package/dist/chunk-6PZHSHU3.js +0 -2
- package/dist/chunk-CHNUE46K.cjs +0 -2
- package/dist/chunk-LCQZIWBO.cjs +0 -2
- package/dist/entity-adapter.interface-BDgbSxhq.d.cts +0 -33
- package/dist/entity-adapter.interface-BDgbSxhq.d.ts +0 -33
- package/dist/listing-config-options.interface-ZJYY_ZvR.d.cts +0 -12
- package/dist/listing-config-options.interface-ZJYY_ZvR.d.ts +0 -12
- package/dist/map-provider.interface-BMnwW3ob.d.cts +0 -37
- package/dist/map-provider.interface-BxexMT3X.d.ts +0 -37
- package/dist/presets/rental/index.cjs +0 -2
- package/dist/presets/rental/index.d.cts +0 -266
- package/dist/presets/rental/index.d.ts +0 -266
- package/dist/presets/rental/index.js +0 -2
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ pnpm add react-listing-engine
|
|
|
27
27
|
|
|
28
28
|
## Quickstart
|
|
29
29
|
|
|
30
|
-
Minimal setup
|
|
30
|
+
Minimal setup — one dataset, one filter, Google Maps, and the styled `/shadcn` layout. Define your own entity + filter shapes and back them with an `EntityAdapter`:
|
|
31
31
|
|
|
32
32
|
```tsx
|
|
33
33
|
import {
|
|
@@ -36,26 +36,38 @@ import {
|
|
|
36
36
|
withDataset,
|
|
37
37
|
withFilters,
|
|
38
38
|
withMap,
|
|
39
|
+
type EntityAdapter,
|
|
40
|
+
type FilterControlProps,
|
|
39
41
|
} from 'react-listing-engine';
|
|
40
42
|
import { ListingComponentsProviderWithDefaults, ListingLayout } from 'react-listing-engine/shadcn';
|
|
41
43
|
import { googleProvider } from 'react-listing-engine/maps/google';
|
|
42
|
-
import {
|
|
43
|
-
propertiesDataset,
|
|
44
|
-
withRentalFilters,
|
|
45
|
-
type PropertiesApiPort,
|
|
46
|
-
type PropertyEntity,
|
|
47
|
-
type RentalFilters,
|
|
48
|
-
} from 'react-listing-engine/presets/rental';
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
interface Property { id: string; title: string; price: number; lat: number; lng: number }
|
|
46
|
+
interface Filters { q?: string }
|
|
47
|
+
|
|
48
|
+
// Your API-backed adapter: `list(filters, page)` for the results, `getPoints(filters, bounds)`
|
|
49
|
+
// for the map pins. The engine never makes an HTTP call itself.
|
|
50
|
+
declare const adapter: EntityAdapter<Property, Filters>;
|
|
51
|
+
|
|
52
|
+
const SearchControl = ({ onChange, value }: FilterControlProps<string>) => (
|
|
53
|
+
<input onChange={e => onChange(e.target.value)} placeholder="Search" value={value} />
|
|
54
|
+
);
|
|
51
55
|
|
|
52
56
|
export function PropertySearch() {
|
|
53
57
|
return (
|
|
54
|
-
<ListingProvider<
|
|
55
|
-
{...composeListingProviders<
|
|
56
|
-
withMap<
|
|
57
|
-
withDataset(
|
|
58
|
-
withFilters(
|
|
58
|
+
<ListingProvider<Property, Filters>
|
|
59
|
+
{...composeListingProviders<Filters>(
|
|
60
|
+
withMap<Filters>(googleProvider({ apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY! })),
|
|
61
|
+
withDataset({ id: 'properties', adapter, marker: {} }),
|
|
62
|
+
withFilters<Filters>(reg =>
|
|
63
|
+
reg.add<string>({
|
|
64
|
+
key: 'q',
|
|
65
|
+
order: 0,
|
|
66
|
+
render: SearchControl,
|
|
67
|
+
toParams: v => ({ q: v || undefined }),
|
|
68
|
+
fromParams: f => f.q ?? '',
|
|
69
|
+
}),
|
|
70
|
+
),
|
|
59
71
|
)}
|
|
60
72
|
>
|
|
61
73
|
<ListingComponentsProviderWithDefaults>
|
|
@@ -66,13 +78,11 @@ export function PropertySearch() {
|
|
|
66
78
|
}
|
|
67
79
|
```
|
|
68
80
|
|
|
69
|
-
`propertiesApi` only needs to implement `PropertiesApiPort` (`list`, `search`, optional `getById`) against your own backend — the preset never makes an HTTP call itself.
|
|
70
|
-
|
|
71
81
|
## Customization tiers
|
|
72
82
|
|
|
73
83
|
The engine is layered so you can go as deep as you need and stop:
|
|
74
84
|
|
|
75
|
-
1. **Data** — implement `EntityAdapter<TEntity, TFilters>`
|
|
85
|
+
1. **Data** — implement `EntityAdapter<TEntity, TFilters>` against your own API. Nothing in the engine assumes a specific backend or entity shape.
|
|
76
86
|
2. **Structure** — compose the provider with `composeListingProviders(withMap(...), withDataset(...), withFilters(...), withUrlSync(...), withInitialFilters(...), withPrimaryDataset(...), withConfig(...))`. Mutate filters via `FilterRegistry` (`add`/`remove`/`reorder`/`replace`) and layers via `DatasetRegistry` (`add`/`get`/`has`/`list`/`visibleIds`).
|
|
77
87
|
3. **Presentation** — swap any slot via `ListingComponentsProvider` (or start from `ListingComponentsProviderWithDefaults` for the `/shadcn` look and override only what you need). Injectable slots: `Card`, `Marker`, `Popup`, `Sidebar`, `FilterPanel`, `Search`, `Empty`, `Loading`, `ResultHeader`, `Toolbar`. `Marker`/`Popup` are defined but not yet wired into the map's render output (see the Features note above) — every other slot renders as described.
|
|
78
88
|
4. **Layout** — skip `ListingLayout` entirely and arrange the structure-only compound components yourself: `ListingList`, `ListingMap`, `ListingFilters`, `ListingResultHeader`, `ListingToolbar`, `ListingPagination`.
|
|
@@ -93,23 +103,21 @@ const map = googleProvider({
|
|
|
93
103
|
- `loaderOptions` (optional) forwards extra `@googlemaps/js-api-loader` config (language, region, preloaded libraries); `key` is always taken from `apiKey` and can't be overridden there.
|
|
94
104
|
- `DatasetDefinition.clustering` (`{ maxZoom }` or `false`) is implemented by the shipped `googleProvider`: when set, that layer's markers are wrapped in a `MarkerClusterer` (from the OPTIONAL peer dependency `@googlemaps/markerclusterer` — install it to enable clustering; without it, `googleProvider` warns once and falls back to plain, unclustered markers, no crash) with a custom renderer that draws a solid red circle showing the cluster's count. No Mapbox provider ships either; `MapProvider` is the seam if you want to add one.
|
|
95
105
|
|
|
96
|
-
##
|
|
106
|
+
## Multiple marker layers
|
|
97
107
|
|
|
98
|
-
A second marker layer composes onto the same map with one more `withDataset` call:
|
|
108
|
+
A second marker layer (nearby businesses, schools, transit, …) composes onto the same map with one more `withDataset` call — its own `EntityAdapter` and marker:
|
|
99
109
|
|
|
100
110
|
```ts
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}),
|
|
107
|
-
)
|
|
111
|
+
withDataset({
|
|
112
|
+
id: 'businesses',
|
|
113
|
+
adapter: businessesAdapter, // your EntityAdapter for the second layer
|
|
114
|
+
marker: { iconUrl: b => categoryIcons[b.category] },
|
|
115
|
+
})
|
|
108
116
|
```
|
|
109
117
|
|
|
110
|
-
|
|
118
|
+
Additional datasets are **map-only** layers: only the primary dataset (the first one added, or whichever id you pass as `primaryDatasetId` via `withPrimaryDataset`) drives the results list and pagination — implementing `list` on a secondary dataset's adapter has no effect on the list/pagination unless that dataset is made primary.
|
|
111
119
|
|
|
112
|
-
**Filter
|
|
120
|
+
**Filter-shape caveat.** `ListingEngine.loadPoints` calls every visible layer's `getPoints` with the *primary* dataset's `TFilters` — there's a single filter state per engine, not one per layer. A secondary dataset whose filters have a genuinely different shape is **not** driven by the engine's filter state at all; the engine's filter object simply isn't in that shape by the time it reaches the layer's adapter. Filter such a layer at construction instead — close over the restriction in the adapter you hand to `withDataset` — rather than reading it from `useListingFilters()`.
|
|
113
121
|
|
|
114
122
|
## Styled adapter
|
|
115
123
|
|
|
@@ -126,7 +134,7 @@ It needs Tailwind to see its class names and the shadcn-style CSS variables to b
|
|
|
126
134
|
@import "tailwindcss";
|
|
127
135
|
@source "../node_modules/react-listing-engine/dist/**/*.{js,cjs}";
|
|
128
136
|
```
|
|
129
|
-
- or define the semantic tokens it reads yourself (`--color-background`, `--color-foreground`, `--color-card`, `--color-popover`, `--color-border`, `--color-primary`, `--color-secondary`, `--color-muted`, `--color-accent`, `--color-destructive`, plus `-foreground` variants), the same set any shadcn-based project already ships.
|
|
137
|
+
- or define the semantic tokens it reads yourself (`--color-background`, `--color-foreground`, `--color-card`, `--color-popover`, `--color-border`, `--color-primary`, `--color-secondary`, `--color-muted`, `--color-accent`, `--color-destructive`, plus `-foreground` variants), the same set any shadcn-based project already ships.
|
|
130
138
|
|
|
131
139
|
## Hooks
|
|
132
140
|
|
|
@@ -138,17 +146,6 @@ It needs Tailwind to see its class names and the shadcn-style CSS variables to b
|
|
|
138
146
|
- `useListingLayer(id)` — one dataset's visibility, points, and a `toggle()`.
|
|
139
147
|
- `useListingEvent(type | '*', handler)` — subscribe to engine events for the component's lifetime.
|
|
140
148
|
|
|
141
|
-
## Examples
|
|
142
|
-
|
|
143
|
-
[`examples/basic`](./examples/basic) is a Vite app with four scenarios, run locally (`pnpm install && pnpm dev` inside that folder):
|
|
144
|
-
|
|
145
|
-
- **Properties only** — one dataset, the shipped rental filters, and the styled `/shadcn` defaults.
|
|
146
|
-
- **Properties + businesses** — a second nearby-businesses marker layer composed alongside the properties dataset.
|
|
147
|
-
- **Custom components** — `ListingComponentsProvider` with an app-authored `Card` and `Empty` slot.
|
|
148
|
-
- **Custom filters** — `withFilters(reg => reg.add/remove/reorder)` mutating the shipped rental filter set.
|
|
149
|
-
|
|
150
|
-
Each scenario works without a Google Maps key (the map is simply not rendered; a notice explains why) — set `VITE_GOOGLE_MAPS_KEY` in `examples/basic/.env` to see the map layer too.
|
|
151
|
-
|
|
152
149
|
## Support
|
|
153
150
|
|
|
154
151
|
If `react-listing-engine` saves you time, consider sponsoring continued maintenance:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as EntityAdapter, M as MapPoint } from './map-provider.interface-DT-v1plm.cjs';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ComponentType, ReactNode } from 'react';
|
|
4
4
|
|
|
@@ -34,6 +34,17 @@ interface DatasetDefinition<TEntity, TFilters> {
|
|
|
34
34
|
visible?: () => boolean;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
declare enum PaginationMode {
|
|
38
|
+
Paged = "paged",
|
|
39
|
+
Infinite = "infinite"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface IListingConfigOptions {
|
|
43
|
+
pagination: PaginationMode;
|
|
44
|
+
pageSize: number;
|
|
45
|
+
debounceMs: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
/**
|
|
38
49
|
* Framework-free registry for `FilterDefinition`s: programmatic add / remove /
|
|
39
50
|
* reorder / replace, plus folding raw control values into `TFilters`
|
|
@@ -117,4 +128,4 @@ declare function ListingComponentsProvider(props: Partial<IListingComponents> &
|
|
|
117
128
|
}): react.JSX.Element;
|
|
118
129
|
declare function useListingComponents(): IListingComponents;
|
|
119
130
|
|
|
120
|
-
export { type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type
|
|
131
|
+
export { type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingComponentsProvider as L, type MarkerRenderer as M, PaginationMode as P, type IListingToolbarProps as a, type FilterControlProps as b, type FilterDefinition as c, type IListingCardProps as d, type IListingComponents as e, type IListingEmptyProps as f, type IListingFilterPanelProps as g, type IListingLoadingProps as h, type IListingMarkerProps as i, type IListingPopupProps as j, type IListingResultHeaderProps as k, type IListingSearchProps as l, type IListingSidebarProps as m, useListingComponents as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as EntityAdapter, M as MapPoint } from './map-provider.interface-DT-v1plm.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ComponentType, ReactNode } from 'react';
|
|
4
4
|
|
|
@@ -34,6 +34,17 @@ interface DatasetDefinition<TEntity, TFilters> {
|
|
|
34
34
|
visible?: () => boolean;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
declare enum PaginationMode {
|
|
38
|
+
Paged = "paged",
|
|
39
|
+
Infinite = "infinite"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface IListingConfigOptions {
|
|
43
|
+
pagination: PaginationMode;
|
|
44
|
+
pageSize: number;
|
|
45
|
+
debounceMs: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
/**
|
|
38
49
|
* Framework-free registry for `FilterDefinition`s: programmatic add / remove /
|
|
39
50
|
* reorder / replace, plus folding raw control values into `TFilters`
|
|
@@ -117,4 +128,4 @@ declare function ListingComponentsProvider(props: Partial<IListingComponents> &
|
|
|
117
128
|
}): react.JSX.Element;
|
|
118
129
|
declare function useListingComponents(): IListingComponents;
|
|
119
130
|
|
|
120
|
-
export { type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type
|
|
131
|
+
export { type ClusterOptions as C, type DatasetDefinition as D, FilterRegistry as F, type IListingConfigOptions as I, ListingComponentsProvider as L, type MarkerRenderer as M, PaginationMode as P, type IListingToolbarProps as a, type FilterControlProps as b, type FilterDefinition as c, type IListingCardProps as d, type IListingComponents as e, type IListingEmptyProps as f, type IListingFilterPanelProps as g, type IListingLoadingProps as h, type IListingMarkerProps as i, type IListingPopupProps as j, type IListingResultHeaderProps as k, type IListingSearchProps as l, type IListingSidebarProps as m, useListingComponents as u };
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;"use client";
|
|
2
|
-
var
|
|
2
|
+
var _chunk2VUHLHHXcjs = require('./chunk-2VUHLHHX.cjs');var _chunkRXHR66FScjs = require('./chunk-RXHR66FS.cjs');var _chunkEYXV5OMYcjs = require('./chunk-EYXV5OMY.cjs');var y=(o=>(o.Paged="paged",o.Infinite="infinite",o))(y||{});var h=(r=>(r.FiltersChanged="FiltersChanged",r.ResultsLoaded="ResultsLoaded",r.PointClicked="PointClicked",r.BoundsChanged="BoundsChanged",r.LayerToggled="LayerToggled",r))(h||{});var d= (_class =class{__init() {this.listeners=new Set}constructor(e={}){;_class.prototype.__init.call(this);this.query={...e}}getQuery(){return{...this.query}}setQuery(e){this.query={...e},this.notify()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notify(){for(let e of[...this.listeners])e()}}, _class);var c=class{constructor(e={}){this.mode=_nullishCoalesce(e.mode, () => ("replace"))}getQuery(){if(typeof window>"u")return{};let e=new URLSearchParams(window.location.search),o={};for(let[i,s]of e)s!==""&&(o[i]=s);return o}setQuery(e){if(typeof window>"u")return;let o=new URLSearchParams;for(let[m,u]of Object.entries(e))u===void 0||u===""||o.set(m,u);let i=o.toString(),s=i?`?${i}`:"";if(s===window.location.search)return;let r=`${window.location.pathname}${s}${window.location.hash}`;this.mode==="push"?window.history.pushState(window.history.state,"",r):window.history.replaceState(window.history.state,"",r)}subscribe(e){return typeof window>"u"?()=>{}:(window.addEventListener("popstate",e),()=>{window.removeEventListener("popstate",e)})}};var _jsxruntime = require('react/jsx-runtime');function _({children:t}){let{Toolbar:e}=_chunkEYXV5OMYcjs.q.call(void 0, );return _jsxruntime.jsx.call(void 0, e,{children:t})}var _react = require('react');function re(){let t=_chunkEYXV5OMYcjs.s.call(void 0, ),e=_chunkEYXV5OMYcjs.t.call(void 0, ),o=_react.useCallback.call(void 0, s=>t.loadPoints(s),[t]),i=_react.useCallback.call(void 0, (s,r)=>t.selectPoint(s,r),[t]);return{bounds:e.bounds,points:e.points,loadPoints:o,selectPoint:i}}function ue(t){let e=_chunkEYXV5OMYcjs.s.call(void 0, ),o=_chunkEYXV5OMYcjs.t.call(void 0, ),i=_react.useCallback.call(void 0, ()=>e.toggleLayer(t),[e,t]);return{visible:_nullishCoalesce(o.layers[t], () => (!0)),points:_nullishCoalesce(o.points[t], () => ([])),toggle:i}}exports.BrowserHistoryPort = c; exports.DatasetRegistry = _chunkEYXV5OMYcjs.c; exports.FilterRegistry = _chunkEYXV5OMYcjs.b; exports.ListingApp = _chunkRXHR66FScjs.p; exports.ListingComponentsProvider = _chunkEYXV5OMYcjs.p; exports.ListingConfig = _chunkEYXV5OMYcjs.f; exports.ListingEngine = _chunkEYXV5OMYcjs.g; exports.ListingEngineContext = _chunkEYXV5OMYcjs.r; exports.ListingEventType = h; exports.ListingFilters = _chunkEYXV5OMYcjs.v; exports.ListingList = _chunkEYXV5OMYcjs.x; exports.ListingMap = _chunkEYXV5OMYcjs.y; exports.ListingPagination = _chunkEYXV5OMYcjs.z; exports.ListingProvider = _chunkEYXV5OMYcjs.B; exports.ListingResultHeader = _chunkEYXV5OMYcjs.A; exports.ListingStore = _chunkEYXV5OMYcjs.a; exports.ListingToolbar = _; exports.MemoryHistoryPort = d; exports.PaginationMode = y; exports.TypedEmitter = _chunkEYXV5OMYcjs.d; exports.UrlSyncController = _chunk2VUHLHHXcjs.a; exports.composeListingProviders = _chunkEYXV5OMYcjs.h; exports.listingDefaultConfig = _chunkEYXV5OMYcjs.e; exports.useListing = _chunkEYXV5OMYcjs.s; exports.useListingComponents = _chunkEYXV5OMYcjs.q; exports.useListingEvent = _chunkRXHR66FScjs.a; exports.useListingFilters = _chunkEYXV5OMYcjs.u; exports.useListingLayer = ue; exports.useListingMap = re; exports.useListingResults = _chunkEYXV5OMYcjs.w; exports.useListingState = _chunkEYXV5OMYcjs.t; exports.withConfig = _chunkEYXV5OMYcjs.i; exports.withDataset = _chunkEYXV5OMYcjs.k; exports.withFilters = _chunkEYXV5OMYcjs.l; exports.withInitialFilters = _chunkEYXV5OMYcjs.n; exports.withMap = _chunkEYXV5OMYcjs.j; exports.withPrimaryDataset = _chunkEYXV5OMYcjs.o; exports.withUrlSync = _chunkEYXV5OMYcjs.m;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { P as Page, B as Bounds, E as EntityId, M as MapPoint, Q as QueryParams, L as LatLng } from './
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
5
|
-
import {
|
|
6
|
-
export {
|
|
7
|
-
import { P as PaginationMode, I as IListingConfigOptions } from './listing-config-options.interface-ZJYY_ZvR.cjs';
|
|
8
|
-
import { H as HistoryPort, U as UrlSyncController } from './url-sync.controller-CsU_QxoS.cjs';
|
|
9
|
-
export { a as UrlSyncEngine, b as UrlSyncOptions } from './url-sync.controller-CsU_QxoS.cjs';
|
|
1
|
+
import { P as Page, B as Bounds, E as EntityId, M as MapPoint, U as Unsubscribe, a as MapProvider, Q as QueryParams, L as LatLng } from './map-provider.interface-DT-v1plm.cjs';
|
|
2
|
+
export { b as EntityAdapter, c as MapHandle, d as MapInitOptions, e as PageRequest, R as RenderedLayer } from './map-provider.interface-DT-v1plm.cjs';
|
|
3
|
+
import { P as PaginationMode, D as DatasetDefinition, I as IListingConfigOptions, F as FilterRegistry, a as IListingToolbarProps } from './components-provider-FinfaqUT.cjs';
|
|
4
|
+
export { C as ClusterOptions, b as FilterControlProps, c as FilterDefinition, d as IListingCardProps, e as IListingComponents, f as IListingEmptyProps, g as IListingFilterPanelProps, h as IListingLoadingProps, i as IListingMarkerProps, j as IListingPopupProps, k as IListingResultHeaderProps, l as IListingSearchProps, m as IListingSidebarProps, L as ListingComponentsProvider, M as MarkerRenderer, u as useListingComponents } from './components-provider-FinfaqUT.cjs';
|
|
5
|
+
import { H as HistoryPort, U as UrlSyncController } from './url-sync.controller-DXSIWgTa.cjs';
|
|
6
|
+
export { a as UrlSyncEngine, b as UrlSyncOptions } from './url-sync.controller-DXSIWgTa.cjs';
|
|
10
7
|
import * as react from 'react';
|
|
11
8
|
import { ReactNode } from 'react';
|
|
12
|
-
export { L as ListingApp, a as ListingAppProps } from './listing-app-
|
|
9
|
+
export { L as ListingApp, a as ListingAppProps } from './listing-app-BMoMKD4c.cjs';
|
|
13
10
|
|
|
14
11
|
declare enum ListingEventType {
|
|
15
12
|
FiltersChanged = "FiltersChanged",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { P as Page, B as Bounds, E as EntityId, M as MapPoint, Q as QueryParams, L as LatLng } from './
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
5
|
-
import {
|
|
6
|
-
export {
|
|
7
|
-
import { P as PaginationMode, I as IListingConfigOptions } from './listing-config-options.interface-ZJYY_ZvR.js';
|
|
8
|
-
import { H as HistoryPort, U as UrlSyncController } from './url-sync.controller-DX67JivW.js';
|
|
9
|
-
export { a as UrlSyncEngine, b as UrlSyncOptions } from './url-sync.controller-DX67JivW.js';
|
|
1
|
+
import { P as Page, B as Bounds, E as EntityId, M as MapPoint, U as Unsubscribe, a as MapProvider, Q as QueryParams, L as LatLng } from './map-provider.interface-DT-v1plm.js';
|
|
2
|
+
export { b as EntityAdapter, c as MapHandle, d as MapInitOptions, e as PageRequest, R as RenderedLayer } from './map-provider.interface-DT-v1plm.js';
|
|
3
|
+
import { P as PaginationMode, D as DatasetDefinition, I as IListingConfigOptions, F as FilterRegistry, a as IListingToolbarProps } from './components-provider-cWVWEDXC.js';
|
|
4
|
+
export { C as ClusterOptions, b as FilterControlProps, c as FilterDefinition, d as IListingCardProps, e as IListingComponents, f as IListingEmptyProps, g as IListingFilterPanelProps, h as IListingLoadingProps, i as IListingMarkerProps, j as IListingPopupProps, k as IListingResultHeaderProps, l as IListingSearchProps, m as IListingSidebarProps, L as ListingComponentsProvider, M as MarkerRenderer, u as useListingComponents } from './components-provider-cWVWEDXC.js';
|
|
5
|
+
import { H as HistoryPort, U as UrlSyncController } from './url-sync.controller-DK5W_0OZ.js';
|
|
6
|
+
export { a as UrlSyncEngine, b as UrlSyncOptions } from './url-sync.controller-DK5W_0OZ.js';
|
|
10
7
|
import * as react from 'react';
|
|
11
8
|
import { ReactNode } from 'react';
|
|
12
|
-
export { L as ListingApp, a as ListingAppProps } from './listing-app-
|
|
9
|
+
export { L as ListingApp, a as ListingAppProps } from './listing-app-BSJKGh7k.js';
|
|
13
10
|
|
|
14
11
|
declare enum ListingEventType {
|
|
15
12
|
FiltersChanged = "FiltersChanged",
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{a as
|
|
2
|
+
import{a as S}from"./chunk-35KYEBAC.js";import{a as K,p as f}from"./chunk-CGT3RHJ7.js";import{A as J,B as N,a as P,b as L,c as x,d as b,e as v,f as Q,g as C,h as k,i as q,j as B,k as I,l as H,m as R,n as $,o as O,p as A,q as p,r as F,s as n,t as a,u as T,v as U,w as j,x as z,y as D,z as G}from"./chunk-R3FX2V3N.js";var y=(o=>(o.Paged="paged",o.Infinite="infinite",o))(y||{});var h=(r=>(r.FiltersChanged="FiltersChanged",r.ResultsLoaded="ResultsLoaded",r.PointClicked="PointClicked",r.BoundsChanged="BoundsChanged",r.LayerToggled="LayerToggled",r))(h||{});var d=class{query;listeners=new Set;constructor(e={}){this.query={...e}}getQuery(){return{...this.query}}setQuery(e){this.query={...e},this.notify()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notify(){for(let e of[...this.listeners])e()}};var c=class{mode;constructor(e={}){this.mode=e.mode??"replace"}getQuery(){if(typeof window>"u")return{};let e=new URLSearchParams(window.location.search),o={};for(let[i,s]of e)s!==""&&(o[i]=s);return o}setQuery(e){if(typeof window>"u")return;let o=new URLSearchParams;for(let[m,u]of Object.entries(e))u===void 0||u===""||o.set(m,u);let i=o.toString(),s=i?`?${i}`:"";if(s===window.location.search)return;let r=`${window.location.pathname}${s}${window.location.hash}`;this.mode==="push"?window.history.pushState(window.history.state,"",r):window.history.replaceState(window.history.state,"",r)}subscribe(e){return typeof window>"u"?()=>{}:(window.addEventListener("popstate",e),()=>{window.removeEventListener("popstate",e)})}};import{jsx as w}from"react/jsx-runtime";function _({children:t}){let{Toolbar:e}=p();return w(e,{children:t})}import{useCallback as l}from"react";function re(){let t=n(),e=a(),o=l(s=>t.loadPoints(s),[t]),i=l((s,r)=>t.selectPoint(s,r),[t]);return{bounds:e.bounds,points:e.points,loadPoints:o,selectPoint:i}}import{useCallback as g}from"react";function ue(t){let e=n(),o=a(),i=g(()=>e.toggleLayer(t),[e,t]);return{visible:o.layers[t]??!0,points:o.points[t]??[],toggle:i}}export{c as BrowserHistoryPort,x as DatasetRegistry,L as FilterRegistry,f as ListingApp,A as ListingComponentsProvider,Q as ListingConfig,C as ListingEngine,F as ListingEngineContext,h as ListingEventType,U as ListingFilters,z as ListingList,D as ListingMap,G as ListingPagination,N as ListingProvider,J as ListingResultHeader,P as ListingStore,_ as ListingToolbar,d as MemoryHistoryPort,y as PaginationMode,b as TypedEmitter,S as UrlSyncController,k as composeListingProviders,v as listingDefaultConfig,n as useListing,p as useListingComponents,K as useListingEvent,T as useListingFilters,ue as useListingLayer,re as useListingMap,j as useListingResults,a as useListingState,q as withConfig,I as withDataset,H as withFilters,$ as withInitialFilters,B as withMap,O as withPrimaryDataset,R as withUrlSync};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { L as LatLng } from './
|
|
4
|
-
import {
|
|
5
|
-
import { D as DatasetDefinition, F as FilterRegistry, d as IListingComponents } from './components-provider-CjMxkxrP.js';
|
|
6
|
-
import { I as IListingConfigOptions } from './listing-config-options.interface-ZJYY_ZvR.js';
|
|
3
|
+
import { L as LatLng, a as MapProvider } from './map-provider.interface-DT-v1plm.cjs';
|
|
4
|
+
import { D as DatasetDefinition, F as FilterRegistry, e as IListingComponents, I as IListingConfigOptions } from './components-provider-FinfaqUT.cjs';
|
|
7
5
|
|
|
8
6
|
type BottomNavView = 'list' | 'map';
|
|
9
7
|
interface IBottomNavAction {
|
|
@@ -133,7 +131,7 @@ interface ListingAppProps<TFilters> {
|
|
|
133
131
|
* `withDataset` doc comment.
|
|
134
132
|
*/
|
|
135
133
|
datasets: DatasetDefinition<any, TFilters>[];
|
|
136
|
-
/**
|
|
134
|
+
/** A `(reg) => { reg.add(...); }` callback that registers your filters -- forwarded verbatim to `withFilters`. */
|
|
137
135
|
filters?: (reg: FilterRegistry<TFilters>) => void;
|
|
138
136
|
/** A ready `MapProvider`, or `{ apiKey, mapId? }` to build a `googleProvider` internally. Omit for no map (the styled layout shows a "Map unavailable" fallback). */
|
|
139
137
|
map?: ListingAppMapProp;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { L as LatLng } from './
|
|
4
|
-
import {
|
|
5
|
-
import { D as DatasetDefinition, F as FilterRegistry, d as IListingComponents } from './components-provider-CF0Mo0B8.cjs';
|
|
6
|
-
import { I as IListingConfigOptions } from './listing-config-options.interface-ZJYY_ZvR.cjs';
|
|
3
|
+
import { L as LatLng, a as MapProvider } from './map-provider.interface-DT-v1plm.js';
|
|
4
|
+
import { D as DatasetDefinition, F as FilterRegistry, e as IListingComponents, I as IListingConfigOptions } from './components-provider-cWVWEDXC.js';
|
|
7
5
|
|
|
8
6
|
type BottomNavView = 'list' | 'map';
|
|
9
7
|
interface IBottomNavAction {
|
|
@@ -133,7 +131,7 @@ interface ListingAppProps<TFilters> {
|
|
|
133
131
|
* `withDataset` doc comment.
|
|
134
132
|
*/
|
|
135
133
|
datasets: DatasetDefinition<any, TFilters>[];
|
|
136
|
-
/**
|
|
134
|
+
/** A `(reg) => { reg.add(...); }` callback that registers your filters -- forwarded verbatim to `withFilters`. */
|
|
137
135
|
filters?: (reg: FilterRegistry<TFilters>) => void;
|
|
138
136
|
/** A ready `MapProvider`, or `{ apiKey, mapId? }` to build a `googleProvider` internally. Omit for no map (the styled layout shows a "Map unavailable" fallback). */
|
|
139
137
|
map?: ListingAppMapProp;
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
interface MapHandle {
|
|
43
|
+
readonly raw: unknown;
|
|
44
|
+
}
|
|
45
|
+
interface RenderedLayer {
|
|
46
|
+
id: string;
|
|
47
|
+
markers: Array<{
|
|
48
|
+
id: string | number;
|
|
49
|
+
position: LatLng;
|
|
50
|
+
iconUrl?: string;
|
|
51
|
+
element?: HTMLElement;
|
|
52
|
+
}>;
|
|
53
|
+
clustering?: {
|
|
54
|
+
maxZoom?: number;
|
|
55
|
+
} | false;
|
|
56
|
+
onMarkerClick?(id: string | number): void;
|
|
57
|
+
}
|
|
58
|
+
type Unsubscribe = () => void;
|
|
59
|
+
interface MapProvider {
|
|
60
|
+
mount(el: HTMLElement, opts: MapInitOptions): Promise<MapHandle> | MapHandle;
|
|
61
|
+
renderLayer(handle: MapHandle, layer: RenderedLayer): Unsubscribe;
|
|
62
|
+
onBoundsChange(handle: MapHandle, cb: (b: Bounds) => void): Unsubscribe;
|
|
63
|
+
fitBounds(handle: MapHandle, b: Bounds): void;
|
|
64
|
+
destroy(handle: MapHandle): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
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, PageRequest as e };
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
interface MapHandle {
|
|
43
|
+
readonly raw: unknown;
|
|
44
|
+
}
|
|
45
|
+
interface RenderedLayer {
|
|
46
|
+
id: string;
|
|
47
|
+
markers: Array<{
|
|
48
|
+
id: string | number;
|
|
49
|
+
position: LatLng;
|
|
50
|
+
iconUrl?: string;
|
|
51
|
+
element?: HTMLElement;
|
|
52
|
+
}>;
|
|
53
|
+
clustering?: {
|
|
54
|
+
maxZoom?: number;
|
|
55
|
+
} | false;
|
|
56
|
+
onMarkerClick?(id: string | number): void;
|
|
57
|
+
}
|
|
58
|
+
type Unsubscribe = () => void;
|
|
59
|
+
interface MapProvider {
|
|
60
|
+
mount(el: HTMLElement, opts: MapInitOptions): Promise<MapHandle> | MapHandle;
|
|
61
|
+
renderLayer(handle: MapHandle, layer: RenderedLayer): Unsubscribe;
|
|
62
|
+
onBoundsChange(handle: MapHandle, cb: (b: Bounds) => void): Unsubscribe;
|
|
63
|
+
fitBounds(handle: MapHandle, b: Bounds): void;
|
|
64
|
+
destroy(handle: MapHandle): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
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, PageRequest as e };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { APIOptions } from '@googlemaps/js-api-loader';
|
|
2
|
-
import {
|
|
3
|
-
import '../../entity-adapter.interface-BDgbSxhq.cjs';
|
|
2
|
+
import { a as MapProvider } from '../../map-provider.interface-DT-v1plm.cjs';
|
|
4
3
|
|
|
5
4
|
interface GoogleMapsProviderConfig {
|
|
6
5
|
/** Google Maps JavaScript API key. Required -- there is no hardcoded fallback. */
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { APIOptions } from '@googlemaps/js-api-loader';
|
|
2
|
-
import {
|
|
3
|
-
import '../../entity-adapter.interface-BDgbSxhq.js';
|
|
2
|
+
import { a as MapProvider } from '../../map-provider.interface-DT-v1plm.js';
|
|
4
3
|
|
|
5
4
|
interface GoogleMapsProviderConfig {
|
|
6
5
|
/** Google Maps JavaScript API key. Required -- there is no hardcoded fallback. */
|
package/dist/shadcn/index.cjs
CHANGED
|
@@ -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 _chunkEYXV5OMYcjs = require('../chunk-EYXV5OMY.cjs');var _chunkLCQZIWBOcjs = require('../chunk-LCQZIWBO.cjs');var _chunk2VUHLHHXcjs = require('../chunk-2VUHLHHX.cjs');var _jsxruntime = require('react/jsx-runtime');function oe(e){return typeof e!="number"?e:new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:0}).format(e)}function w({item:e,selected:i,onSelect:t}){let r=_nullishCoalesce(e, () => ({})),l=_chunkLCQZIWBOcjs.a.call(void 0, "flex w-full flex-col overflow-hidden rounded-lg border bg-card text-left text-card-foreground shadow-sm","motion-safe:transition-shadow",t&&"hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",i&&"ring-2 ring-ring"),a=_jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment,{children:[r.imageUrl&&_jsxruntime.jsx.call(void 0, "img",{src:r.imageUrl,alt:_nullishCoalesce(r.title, () => ("")),className:"aspect-video w-full rounded-t-lg object-cover"}),_jsxruntime.jsxs.call(void 0, "div",{className:"flex flex-1 flex-col gap-1 p-3",children:[_jsxruntime.jsxs.call(void 0, "div",{className:"flex items-start justify-between gap-2",children:[r.title&&_jsxruntime.jsx.call(void 0, "span",{className:"font-medium",children:r.title}),r.badge&&_jsxruntime.jsx.call(void 0, "span",{className:"shrink-0 rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground",children:r.badge})]}),r.subtitle&&_jsxruntime.jsx.call(void 0, "span",{className:"text-sm text-muted-foreground",children:r.subtitle}),r.price!=null&&_jsxruntime.jsx.call(void 0, "span",{className:"mt-1 font-semibold tabular-nums",children:oe(r.price)})]})]});return t?_jsxruntime.jsx.call(void 0, "button",{type:"button",onClick:t,"aria-pressed":_nullishCoalesce(i, () => (!1)),className:l,children:a}):_jsxruntime.jsx.call(void 0, "article",{className:l,children:a})}function C(e){return _jsxruntime.jsxs.call(void 0, "div",{role:"status",className:"flex flex-col items-center justify-center gap-2 px-4 py-12 text-center text-muted-foreground",children:[_jsxruntime.jsxs.call(void 0, "svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",className:"h-8 w-8","aria-hidden":"true",children:[_jsxruntime.jsx.call(void 0, "circle",{cx:"11",cy:"11",r:"7"}),_jsxruntime.jsx.call(void 0, "path",{d:"m21 21-4.3-4.3"})]}),_jsxruntime.jsx.call(void 0, "p",{className:"text-sm font-medium text-foreground",children:"No results"}),_jsxruntime.jsx.call(void 0, "p",{className:"text-xs text-muted-foreground",children:"Try adjusting your filters or search terms."})]})}function I({children:e}){return _jsxruntime.jsx.call(void 0, "div",{className:"flex flex-col gap-3",children:e})}function D(e){return _jsxruntime.jsx.call(void 0, "div",{className:"flex flex-col gap-3 p-3",role:"status","aria-busy":"true","aria-label":"Loading results",children:Array.from({length:3}).map((i,t)=>_jsxruntime.jsxs.call(void 0, "div",{className:"flex flex-col gap-2 motion-safe:animate-pulse",children:[_jsxruntime.jsx.call(void 0, "div",{className:"aspect-video w-full rounded-md bg-muted"}),_jsxruntime.jsx.call(void 0, "div",{className:"h-4 w-2/3 rounded-md bg-muted"}),_jsxruntime.jsx.call(void 0, "div",{className:"h-3 w-1/3 rounded-md bg-muted"})]},t))})}function M({point:e}){let i=_nullishCoalesce(e.entity, () => ({}));return _jsxruntime.jsx.call(void 0, "span",{className:"rounded-full border bg-background px-2 py-0.5 text-xs font-medium tabular-nums shadow-sm",children:_nullishCoalesce(i.price, () => (""))})}function F({entity:e,onClose:i}){let t=_nullishCoalesce(e, () => ({}));return _jsxruntime.jsxs.call(void 0, "div",{className:"relative w-64 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md",role:"group","aria-label":"Location details",children:[_jsxruntime.jsx.call(void 0, "button",{type:"button",onClick:i,"aria-label":"Close",className:"absolute right-2 top-2 rounded-md p-1 text-muted-foreground motion-safe:transition-colors hover:bg-foreground/[0.06] hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",children:_jsxruntime.jsxs.call(void 0, "svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"h-4 w-4","aria-hidden":"true",children:[_jsxruntime.jsx.call(void 0, "path",{d:"M18 6 6 18"}),_jsxruntime.jsx.call(void 0, "path",{d:"m6 6 12 12"})]})}),_jsxruntime.jsxs.call(void 0, "div",{className:"pr-6",children:[t.title&&_jsxruntime.jsx.call(void 0, "div",{className:"font-medium",children:t.title}),t.subtitle&&_jsxruntime.jsx.call(void 0, "div",{className:"text-sm text-muted-foreground",children:t.subtitle}),t.price!=null&&_jsxruntime.jsx.call(void 0, "div",{className:"mt-1 font-semibold tabular-nums",children:t.price})]})]})}function S({count:e,total:i}){let t=i!=null&&i!==e?`${e} of ${i} results`:`${e} results`;return _jsxruntime.jsx.call(void 0, "div",{className:"text-sm tabular-nums text-muted-foreground",children:t})}function T({value:e,onChange:i,placeholder:t}){return _jsxruntime.jsx.call(void 0, "input",{type:"search",value:e,placeholder:t,onChange:r=>i(r.target.value),"aria-label":_nullishCoalesce(t, () => ("Search")),className:_chunkLCQZIWBOcjs.a.call(void 0, "h-9 w-full rounded-md border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground","focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring")})}function R({children:e}){return _jsxruntime.jsx.call(void 0, "aside",{className:"flex w-full flex-col gap-4 p-4 md:border-r md:border-border",children:e})}function A({children:e}){return _jsxruntime.jsx.call(void 0, "div",{className:"flex items-center gap-2 border-b p-2",children:e})}var g={Card:w,Marker:M,Popup:F,Sidebar:R,FilterPanel:I,Search:T,Empty:C,Loading:D,ResultHeader:S,Toolbar:A};function fe({children:e}){return _jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.p,{...g,children:e})}var _react = require('react');var ve=_jsxruntime.jsx.call(void 0, "p",{className:"px-4 text-center text-sm text-muted-foreground",children:"Map unavailable - provide a Google Maps API key"});function E({search:e,className:i,toolbarEnd:t,autoFetch:r=!0,mapCenter:l,mapZoom:a}){let p=_chunkEYXV5OMYcjs.s.call(void 0, ),{Search:u}=_chunkEYXV5OMYcjs.q.call(void 0, ),[f,y]=_react.useState.call(void 0, "list");_react.useEffect.call(void 0, ()=>{r!==!1&&p.applyFilters({})},[p,r]);let h=f==="map"?"hidden md:block":"block",P=f==="list"?"hidden md:block":"block";return _jsxruntime.jsxs.call(void 0, "div",{className:_chunkLCQZIWBOcjs.a.call(void 0, "flex h-full min-h-0 w-full flex-col bg-background text-foreground",i),"data-slot":"listing-layout",children:[_jsxruntime.jsxs.call(void 0, "div",{className:"sticky top-0 z-10 flex flex-wrap items-end gap-3 border-b border-border bg-background p-3","data-slot":"listing-layout-filter-bar",children:[e&&_jsxruntime.jsx.call(void 0, "div",{className:"w-full min-w-0 sm:w-auto sm:max-w-xs sm:flex-1",children:_jsxruntime.jsx.call(void 0, u,{value:e.value,onChange:e.onChange,placeholder:e.placeholder})}),_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.v,{className:"flex flex-wrap items-end gap-3",groupClassName:"min-w-0"}),_jsxruntime.jsxs.call(void 0, "div",{className:"ml-auto flex items-center gap-3",children:[_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.A,{}),t]})]}),_jsxruntime.jsx.call(void 0, "div",{className:"flex items-center justify-center gap-1 border-b border-border bg-background p-2 md:hidden","data-slot":"listing-layout-mobile-toggle",children:_jsxruntime.jsx.call(void 0, "div",{role:"group","aria-label":"View",className:"inline-flex rounded-md border border-border p-0.5",children:[{view:"list",label:"List"},{view:"map",label:"Map"}].map(({view:d,label:n})=>_jsxruntime.jsx.call(void 0, "button",{type:"button","aria-pressed":f===d,onClick:()=>y(d),className:_chunkLCQZIWBOcjs.a.call(void 0, "rounded-[5px] px-3 py-1 text-sm font-medium motion-safe:transition-colors",f===d?"bg-primary text-primary-foreground":"text-muted-foreground hover:bg-foreground/[0.06] hover:text-foreground"),children:n},d))})}),_jsxruntime.jsxs.call(void 0, "div",{className:"grid min-h-0 flex-1 md:grid-cols-[minmax(340px,42%)_1fr]","data-slot":"listing-layout-split",children:[_jsxruntime.jsxs.call(void 0, "div",{className:_chunkLCQZIWBOcjs.a.call(void 0, "min-h-0 overflow-y-auto p-3",h),"data-slot":"listing-layout-list",children:[_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.x,{className:"grid content-start gap-3 [grid-template-columns:repeat(auto-fill,minmax(200px,1fr))]"}),_jsxruntime.jsx.call(void 0, "div",{className:"mt-4 flex justify-center",children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.z,{})})]}),_jsxruntime.jsx.call(void 0, "div",{className:_chunkLCQZIWBOcjs.a.call(void 0, "min-h-0 md:sticky md:top-0",P),"data-slot":"listing-layout-map",children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.y,{center:l,zoom:a,fallback:ve})})]})]})}function ee(e){return"provider"in e}function ye(e){let i=e!=null&&!ee(e),t=i?e.apiKey:void 0,r=i?e.mapId:void 0,[l,a]=_react.useState.call(void 0, ()=>!e||ee(e)?{ready:!0,provider:_optionalChain([e, 'optionalAccess', _2 => _2.provider])}:{ready:!1});return _react.useEffect.call(void 0, ()=>{if(!t)return;let p=!1;return Promise.resolve().then(() => _interopRequireWildcard(require("../maps/google/index.cjs"))).then(({googleProvider:u})=>{p||a({ready:!0,provider:u({apiKey:t,mapId:r})})}),()=>{p=!0}},[t,r]),l}function he(e){let{datasets:i,filters:t,map:r,components:l,urlSync:a,initialFilters:p,config:u,className:f,search:y,autoFetch:h}=e,{ready:P,provider:d}=ye(r);if(!P)return null;let n=[];for(let ie of i)n.push(_chunkEYXV5OMYcjs.k.call(void 0, ie));t&&n.push(_chunkEYXV5OMYcjs.l.call(void 0, t)),d&&n.push(_chunkEYXV5OMYcjs.j.call(void 0, d)),a instanceof _chunk2VUHLHHXcjs.a&&n.push(_chunkEYXV5OMYcjs.m.call(void 0, a)),p&&n.push(_chunkEYXV5OMYcjs.n.call(void 0, p)),u&&n.push(_chunkEYXV5OMYcjs.i.call(void 0, u));let te=_chunkEYXV5OMYcjs.h.call(void 0, ...n),re={...g,...l};return _jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.B,{...te,children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.p,{...re,children:_jsxruntime.jsx.call(void 0, E,{className:f,search:y,autoFetch:h,mapCenter:_optionalChain([r, 'optionalAccess', _3 => _3.center]),mapZoom:_optionalChain([r, 'optionalAccess', _4 => _4.zoom])})})})}exports.DefaultCard = w; exports.DefaultEmpty = C; exports.DefaultFilterPanel = I; exports.DefaultLoading = D; exports.DefaultMarker = M; exports.DefaultPopup = F; exports.DefaultResultHeader = S; exports.DefaultSearch = T; exports.DefaultSidebar = R; exports.DefaultToolbar = A; exports.ListingApp = he; exports.ListingComponentsProviderWithDefaults = fe; exports.ListingLayout = E; exports.cn = _chunkLCQZIWBOcjs.a; exports.shadcnDefaultComponents = g;
|
|
2
|
+
var _chunk2VUHLHHXcjs = require('../chunk-2VUHLHHX.cjs');var _chunkEYXV5OMYcjs = require('../chunk-EYXV5OMY.cjs');var _clsx = require('clsx');var _tailwindmerge = require('tailwind-merge');function s(...e){return _tailwindmerge.twMerge.call(void 0, _clsx.clsx.call(void 0, e))}var _jsxruntime = require('react/jsx-runtime');function ae(e){return typeof e!="number"?e:new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:0}).format(e)}function w({item:e,selected:o,onSelect:t}){let r=_nullishCoalesce(e, () => ({})),l=s("flex w-full flex-col overflow-hidden rounded-lg border bg-card text-left text-card-foreground shadow-sm","motion-safe:transition-shadow",t&&"hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",o&&"ring-2 ring-ring"),a=_jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment,{children:[r.imageUrl&&_jsxruntime.jsx.call(void 0, "img",{src:r.imageUrl,alt:_nullishCoalesce(r.title, () => ("")),className:"aspect-video w-full rounded-t-lg object-cover"}),_jsxruntime.jsxs.call(void 0, "div",{className:"flex flex-1 flex-col gap-1 p-3",children:[_jsxruntime.jsxs.call(void 0, "div",{className:"flex items-start justify-between gap-2",children:[r.title&&_jsxruntime.jsx.call(void 0, "span",{className:"font-medium",children:r.title}),r.badge&&_jsxruntime.jsx.call(void 0, "span",{className:"shrink-0 rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground",children:r.badge})]}),r.subtitle&&_jsxruntime.jsx.call(void 0, "span",{className:"text-sm text-muted-foreground",children:r.subtitle}),r.price!=null&&_jsxruntime.jsx.call(void 0, "span",{className:"mt-1 font-semibold tabular-nums",children:ae(r.price)})]})]});return t?_jsxruntime.jsx.call(void 0, "button",{type:"button",onClick:t,"aria-pressed":_nullishCoalesce(o, () => (!1)),className:l,children:a}):_jsxruntime.jsx.call(void 0, "article",{className:l,children:a})}function C(e){return _jsxruntime.jsxs.call(void 0, "div",{role:"status",className:"flex flex-col items-center justify-center gap-2 px-4 py-12 text-center text-muted-foreground",children:[_jsxruntime.jsxs.call(void 0, "svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",className:"h-8 w-8","aria-hidden":"true",children:[_jsxruntime.jsx.call(void 0, "circle",{cx:"11",cy:"11",r:"7"}),_jsxruntime.jsx.call(void 0, "path",{d:"m21 21-4.3-4.3"})]}),_jsxruntime.jsx.call(void 0, "p",{className:"text-sm font-medium text-foreground",children:"No results"}),_jsxruntime.jsx.call(void 0, "p",{className:"text-xs text-muted-foreground",children:"Try adjusting your filters or search terms."})]})}function I({children:e}){return _jsxruntime.jsx.call(void 0, "div",{className:"flex flex-col gap-3",children:e})}function D(e){return _jsxruntime.jsx.call(void 0, "div",{className:"flex flex-col gap-3 p-3",role:"status","aria-busy":"true","aria-label":"Loading results",children:Array.from({length:3}).map((o,t)=>_jsxruntime.jsxs.call(void 0, "div",{className:"flex flex-col gap-2 motion-safe:animate-pulse",children:[_jsxruntime.jsx.call(void 0, "div",{className:"aspect-video w-full rounded-md bg-muted"}),_jsxruntime.jsx.call(void 0, "div",{className:"h-4 w-2/3 rounded-md bg-muted"}),_jsxruntime.jsx.call(void 0, "div",{className:"h-3 w-1/3 rounded-md bg-muted"})]},t))})}function M({point:e}){let o=_nullishCoalesce(e.entity, () => ({}));return _jsxruntime.jsx.call(void 0, "span",{className:"rounded-full border bg-background px-2 py-0.5 text-xs font-medium tabular-nums shadow-sm",children:_nullishCoalesce(o.price, () => (""))})}function F({entity:e,onClose:o}){let t=_nullishCoalesce(e, () => ({}));return _jsxruntime.jsxs.call(void 0, "div",{className:"relative w-64 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md",role:"group","aria-label":"Location details",children:[_jsxruntime.jsx.call(void 0, "button",{type:"button",onClick:o,"aria-label":"Close",className:"absolute right-2 top-2 rounded-md p-1 text-muted-foreground motion-safe:transition-colors hover:bg-foreground/[0.06] hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",children:_jsxruntime.jsxs.call(void 0, "svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"h-4 w-4","aria-hidden":"true",children:[_jsxruntime.jsx.call(void 0, "path",{d:"M18 6 6 18"}),_jsxruntime.jsx.call(void 0, "path",{d:"m6 6 12 12"})]})}),_jsxruntime.jsxs.call(void 0, "div",{className:"pr-6",children:[t.title&&_jsxruntime.jsx.call(void 0, "div",{className:"font-medium",children:t.title}),t.subtitle&&_jsxruntime.jsx.call(void 0, "div",{className:"text-sm text-muted-foreground",children:t.subtitle}),t.price!=null&&_jsxruntime.jsx.call(void 0, "div",{className:"mt-1 font-semibold tabular-nums",children:t.price})]})]})}function S({count:e,total:o}){let t=o!=null&&o!==e?`${e} of ${o} results`:`${e} results`;return _jsxruntime.jsx.call(void 0, "div",{className:"text-sm tabular-nums text-muted-foreground",children:t})}function T({value:e,onChange:o,placeholder:t}){return _jsxruntime.jsx.call(void 0, "input",{type:"search",value:e,placeholder:t,onChange:r=>o(r.target.value),"aria-label":_nullishCoalesce(t, () => ("Search")),className:s("h-9 w-full rounded-md border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground","focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring")})}function R({children:e}){return _jsxruntime.jsx.call(void 0, "aside",{className:"flex w-full flex-col gap-4 p-4 md:border-r md:border-border",children:e})}function A({children:e}){return _jsxruntime.jsx.call(void 0, "div",{className:"flex items-center gap-2 border-b p-2",children:e})}var g={Card:w,Marker:M,Popup:F,Sidebar:R,FilterPanel:I,Search:T,Empty:C,Loading:D,ResultHeader:S,Toolbar:A};function ge({children:e}){return _jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.p,{...g,children:e})}var _react = require('react');var Le=_jsxruntime.jsx.call(void 0, "p",{className:"px-4 text-center text-sm text-muted-foreground",children:"Map unavailable - provide a Google Maps API key"});function E({search:e,className:o,toolbarEnd:t,autoFetch:r=!0,mapCenter:l,mapZoom:a}){let p=_chunkEYXV5OMYcjs.s.call(void 0, ),{Search:u}=_chunkEYXV5OMYcjs.q.call(void 0, ),[f,y]=_react.useState.call(void 0, "list");_react.useEffect.call(void 0, ()=>{r!==!1&&p.applyFilters({})},[p,r]);let h=f==="map"?"hidden md:block":"block",P=f==="list"?"hidden md:block":"block";return _jsxruntime.jsxs.call(void 0, "div",{className:s("flex h-full min-h-0 w-full flex-col bg-background text-foreground",o),"data-slot":"listing-layout",children:[_jsxruntime.jsxs.call(void 0, "div",{className:"sticky top-0 z-10 flex flex-wrap items-end gap-3 border-b border-border bg-background p-3","data-slot":"listing-layout-filter-bar",children:[e&&_jsxruntime.jsx.call(void 0, "div",{className:"w-full min-w-0 sm:w-auto sm:max-w-xs sm:flex-1",children:_jsxruntime.jsx.call(void 0, u,{value:e.value,onChange:e.onChange,placeholder:e.placeholder})}),_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.v,{className:"flex flex-wrap items-end gap-3",groupClassName:"min-w-0"}),_jsxruntime.jsxs.call(void 0, "div",{className:"ml-auto flex items-center gap-3",children:[_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.A,{}),t]})]}),_jsxruntime.jsx.call(void 0, "div",{className:"flex items-center justify-center gap-1 border-b border-border bg-background p-2 md:hidden","data-slot":"listing-layout-mobile-toggle",children:_jsxruntime.jsx.call(void 0, "div",{role:"group","aria-label":"View",className:"inline-flex rounded-md border border-border p-0.5",children:[{view:"list",label:"List"},{view:"map",label:"Map"}].map(({view:d,label:n})=>_jsxruntime.jsx.call(void 0, "button",{type:"button","aria-pressed":f===d,onClick:()=>y(d),className:s("rounded-[5px] px-3 py-1 text-sm font-medium motion-safe:transition-colors",f===d?"bg-primary text-primary-foreground":"text-muted-foreground hover:bg-foreground/[0.06] hover:text-foreground"),children:n},d))})}),_jsxruntime.jsxs.call(void 0, "div",{className:"grid min-h-0 flex-1 md:grid-cols-[minmax(340px,42%)_1fr]","data-slot":"listing-layout-split",children:[_jsxruntime.jsxs.call(void 0, "div",{className:s("min-h-0 overflow-y-auto p-3",h),"data-slot":"listing-layout-list",children:[_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.x,{className:"grid content-start gap-3 [grid-template-columns:repeat(auto-fill,minmax(200px,1fr))]"}),_jsxruntime.jsx.call(void 0, "div",{className:"mt-4 flex justify-center",children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.z,{})})]}),_jsxruntime.jsx.call(void 0, "div",{className:s("min-h-0 md:sticky md:top-0",P),"data-slot":"listing-layout-map",children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.y,{center:l,zoom:a,fallback:Le})})]})]})}function ee(e){return"provider"in e}function Pe(e){let o=e!=null&&!ee(e),t=o?e.apiKey:void 0,r=o?e.mapId:void 0,[l,a]=_react.useState.call(void 0, ()=>!e||ee(e)?{ready:!0,provider:_optionalChain([e, 'optionalAccess', _2 => _2.provider])}:{ready:!1});return _react.useEffect.call(void 0, ()=>{if(!t)return;let p=!1;return Promise.resolve().then(() => _interopRequireWildcard(require("../maps/google/index.cjs"))).then(({googleProvider:u})=>{p||a({ready:!0,provider:u({apiKey:t,mapId:r})})}),()=>{p=!0}},[t,r]),l}function Ne(e){let{datasets:o,filters:t,map:r,components:l,urlSync:a,initialFilters:p,config:u,className:f,search:y,autoFetch:h}=e,{ready:P,provider:d}=Pe(r);if(!P)return null;let n=[];for(let oe of o)n.push(_chunkEYXV5OMYcjs.k.call(void 0, oe));t&&n.push(_chunkEYXV5OMYcjs.l.call(void 0, t)),d&&n.push(_chunkEYXV5OMYcjs.j.call(void 0, d)),a instanceof _chunk2VUHLHHXcjs.a&&n.push(_chunkEYXV5OMYcjs.m.call(void 0, a)),p&&n.push(_chunkEYXV5OMYcjs.n.call(void 0, p)),u&&n.push(_chunkEYXV5OMYcjs.i.call(void 0, u));let te=_chunkEYXV5OMYcjs.h.call(void 0, ...n),re={...g,...l};return _jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.B,{...te,children:_jsxruntime.jsx.call(void 0, _chunkEYXV5OMYcjs.p,{...re,children:_jsxruntime.jsx.call(void 0, E,{className:f,search:y,autoFetch:h,mapCenter:_optionalChain([r, 'optionalAccess', _3 => _3.center]),mapZoom:_optionalChain([r, 'optionalAccess', _4 => _4.zoom])})})})}exports.DefaultCard = w; exports.DefaultEmpty = C; exports.DefaultFilterPanel = I; exports.DefaultLoading = D; exports.DefaultMarker = M; exports.DefaultPopup = F; exports.DefaultResultHeader = S; exports.DefaultSearch = T; exports.DefaultSidebar = R; exports.DefaultToolbar = A; exports.ListingApp = Ne; exports.ListingComponentsProviderWithDefaults = ge; exports.ListingLayout = E; exports.cn = s; exports.shadcnDefaultComponents = g;
|
package/dist/shadcn/index.d.cts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { L as LatLng } from '../
|
|
5
|
-
import {
|
|
6
|
-
import { I as IListingConfigOptions } from '../listing-config-options.interface-ZJYY_ZvR.cjs';
|
|
7
|
-
import { U as UrlSyncController } from '../url-sync.controller-CsU_QxoS.cjs';
|
|
3
|
+
import { d as IListingCardProps, e as IListingComponents, f as IListingEmptyProps, g as IListingFilterPanelProps, h as IListingLoadingProps, i as IListingMarkerProps, j as IListingPopupProps, k as IListingResultHeaderProps, l as IListingSearchProps, m as IListingSidebarProps, a as IListingToolbarProps, D as DatasetDefinition, F as FilterRegistry, I as IListingConfigOptions } from '../components-provider-FinfaqUT.cjs';
|
|
4
|
+
import { L as LatLng, a as MapProvider } from '../map-provider.interface-DT-v1plm.cjs';
|
|
5
|
+
import { U as UrlSyncController } from '../url-sync.controller-DXSIWgTa.cjs';
|
|
8
6
|
import { ClassValue } from 'clsx';
|
|
9
7
|
|
|
10
8
|
/**
|
|
@@ -216,13 +214,13 @@ interface ListingAppProps<TFilters> {
|
|
|
216
214
|
* -- see `compose-listing-providers.ts`'s `withDataset` doc comment.
|
|
217
215
|
*/
|
|
218
216
|
datasets: DatasetDefinition<any, TFilters>[];
|
|
219
|
-
/**
|
|
217
|
+
/** A `(reg) => { reg.add(...); }` callback that registers your filters -- forwarded verbatim to `withFilters`. */
|
|
220
218
|
filters?: (reg: FilterRegistry<TFilters>) => void;
|
|
221
219
|
/** A ready `MapProvider`, or `{ apiKey, mapId? }` to build a `googleProvider` internally. Omit for no map (the styled layout shows a "Map unavailable" fallback). */
|
|
222
220
|
map?: ListingAppMapProp;
|
|
223
221
|
/** Slot overrides, merged OVER the shadcn styled defaults -- see this file's doc comment for how the merge works. */
|
|
224
222
|
components?: Partial<IListingComponents>;
|
|
225
|
-
/** A `UrlSyncController<TFilters
|
|
223
|
+
/** A `UrlSyncController<TFilters>`, or `true`. `true` is a documented no-op: the library is filters-shape-erased and cannot generically derive a `TFilters <-> QueryParams` mapping, so build a real controller for your own filter shape. */
|
|
226
224
|
urlSync?: UrlSyncController<TFilters> | boolean;
|
|
227
225
|
initialFilters?: TFilters;
|
|
228
226
|
config?: Partial<IListingConfigOptions>;
|