1- import { createSelector , createSelectorMemoized } from '@mui/x-internals/store' ;
2- import { type ChartState , selectorChartDrawingArea } from '@mui/x-charts/internals' ;
3- import {
4- geoAlbers ,
5- geoAlbersUsa ,
6- geoAzimuthalEqualArea ,
7- geoAzimuthalEquidistant ,
8- geoConicConformal ,
9- geoConicEqualArea ,
10- geoConicEquidistant ,
11- geoEqualEarth ,
12- geoEquirectangular ,
13- geoGnomonic ,
14- geoMercator ,
15- geoNaturalEarth1 ,
16- geoOrthographic ,
17- geoStereographic ,
18- geoTransverseMercator ,
19- geoPath ,
20- type ExtendedFeatureCollection ,
21- type GeoProjection ,
22- type GeoPath ,
23- type GeoConicProjection ,
24- } from '@mui/x-charts-vendor/d3-geo' ;
25- import type {
26- D3NamedProjection ,
27- GeoProjectionInput ,
28- UseGeoProjectionSignature ,
29- UseGeoProjectionState ,
30- } from './useGeoProjection.types' ;
31-
32- const PROJECTION_FACTORIES : Record < D3NamedProjection , ( ( ) => GeoProjection ) | undefined > = {
33- // Azimuthal projections (https://d3js.org/d3-geo/azimuthal)
34- azimuthalEqualArea : geoAzimuthalEqualArea ,
35- azimuthalEquidistant : geoAzimuthalEquidistant ,
36- gnomonic : geoGnomonic ,
37- orthographic : geoOrthographic ,
38- stereographic : geoStereographic ,
39-
40- // Conic projections (https://d3js.org/d3-geo/conic)
41- conicConformal : geoConicConformal ,
42- conicEqualArea : geoConicEqualArea ,
43- conicEquidistant : geoConicEquidistant ,
44- albers : geoAlbers ,
45- albersUsa : geoAlbersUsa , // Special composition for the USA with an edge case for Alaska and Hawaii.
46-
47- // Cylindrical projections (https://d3js.org/d3-geo/cylindrical)
48- equirectangular : geoEquirectangular ,
49- mercator : geoMercator ,
50- transverseMercator : geoTransverseMercator ,
51- equalEarth : geoEqualEarth ,
52- naturalEarth1 : geoNaturalEarth1 ,
53- } ;
54-
55- const isConicProjection = ( projection : GeoProjection ) : projection is GeoConicProjection => {
56- return 'parallels' in projection && typeof projection . parallels === 'function' ;
57- } ;
58- export const selectorChartGeoProjectionState = (
59- state : ChartState < [ ] , [ UseGeoProjectionSignature ] > ,
60- ) : UseGeoProjectionState [ 'geoProjection' ] | undefined => state . geoProjection ;
61-
62- export const selectorChartRawGeoData : (
63- state : ChartState < [ ] , [ UseGeoProjectionSignature ] > ,
64- ) => ExtendedFeatureCollection | null = createSelector (
65- selectorChartGeoProjectionState ,
66- ( geoProjection ) => geoProjection ?. geoData ?? null ,
67- ) ;
68-
69- export const selectorChartRawProjection = createSelector (
70- selectorChartGeoProjectionState ,
71- ( geoProjection ) : GeoProjectionInput | null => geoProjection ?. projection ?? null ,
72- ) ;
73-
74- export const selectorChartRawScale = createSelector (
75- selectorChartGeoProjectionState ,
76- ( geoProjection ) : number | null => geoProjection ?. scale ?? null ,
77- ) ;
78-
79- const selectorChartRotate = createSelectorMemoized (
80- selectorChartGeoProjectionState ,
81- ( geoProjection ) : [ number , number ] | null => geoProjection ?. rotate ?? null ,
82- ) ;
83-
84- const selectorChartTranslate = createSelectorMemoized (
85- selectorChartGeoProjectionState ,
86- ( geoProjection ) : [ number , number ] | null => geoProjection ?. translate ?? null ,
87- ) ;
88-
89- const selectorChartParallels = createSelectorMemoized (
90- selectorChartGeoProjectionState ,
91- selectorChartRotate ,
92- ( geoProjection , rotate ) : [ number , number ] =>
93- geoProjection ?. parallels ?? ( rotate ? [ rotate [ 1 ] - 15 , rotate [ 1 ] + 15 ] : [ 30 , 30 ] ) ,
94- ) ;
95- /**
96- * Map a feature's `properties.name` to its index in `geoData.features`,
97- * for fast lookup by name when joining series rows to features.
98- *
99- * Features without a string `properties.name` are skipped; on duplicates,
100- * the first occurrence wins.
101- */
102- export const selectorChartGeoFeatureIndexesByName = createSelectorMemoized (
103- selectorChartRawGeoData ,
104- ( geoData ) : ReadonlyMap < string , number [ ] > => {
105- const map = new Map < string , number [ ] > ( ) ;
106- if ( ! geoData ) {
107- return map ;
108- }
109- geoData . features . forEach ( ( feature , index ) => {
110- const name = feature . properties ?. name ;
111- if ( typeof name !== 'string' ) {
112- return ;
113- }
114- if ( map . has ( name ) ) {
115- map . get ( name ) ! . push ( index ) ;
116- return ;
117- }
118- map . set ( name , [ index ] ) ;
119- } ) ;
120- return map ;
121- } ,
122- ) ;
123-
124- /**
125- * Resolves the raw `projection` input into a ready-to-use `GeoProjection` instance
126- * fitted to the chart's drawing area.
127- *
128- * - String inputs (e.g. `'mercator'`) are mapped to the matching d3-geo factory.
129- * - `GeoProjection` instances are used as-is, then fitted.
130- * - Returns `null` when no projection is registered or the name is unknown.
131- */
132- export const selectorChartProjection = createSelectorMemoized (
133- selectorChartRawProjection ,
134- selectorChartRawGeoData ,
135- selectorChartParallels ,
136- selectorChartRotate ,
137- selectorChartTranslate ,
138- selectorChartRawScale ,
139- selectorChartDrawingArea ,
140- (
141- projectionInput ,
142- geoData ,
143- parallels ,
144- rotate ,
145- translate ,
146- scale ,
147- drawingArea ,
148- ) : GeoProjection | null => {
149- if ( ! projectionInput ) {
150- return null ;
151- }
152- let projection : GeoProjection ;
153- if ( typeof projectionInput === 'string' ) {
154- const factory = PROJECTION_FACTORIES [ projectionInput ] ;
155- if ( ! factory ) {
156- if ( process . env . NODE_ENV !== 'production' ) {
157- console . error (
158- `MUI X Charts: Unknown projection name '${ projectionInput } '. ` +
159- `Expected one of: ${ Object . keys ( PROJECTION_FACTORIES ) . join ( ', ' ) } .` ,
160- ) ;
161- }
162- return null ;
163- }
164- projection = factory ( ) ;
165- if ( isConicProjection ( projection ) ) {
166- projection . parallels ( parallels ) ;
167- }
168- } else {
169- projection = projectionInput ;
170- }
171- if ( geoData ) {
172- if ( isConicProjection ( projection ) ) {
173- if ( rotate ) {
174- projection . rotate ?.( rotate ) ;
175- }
176-
177- if ( ! scale ) {
178- const [ [ x0 , y0 ] , [ x1 , y1 ] ] = geoPath ( projection ) . bounds ( geoData ) ;
179-
180- const currentScale = projection . scale ( ) ;
181-
182- const fitScale = Math . min (
183- currentScale * ( drawingArea . width / ( x1 - x0 ) ) ,
184- currentScale * ( drawingArea . height / ( y1 - y0 ) ) ,
185- ) ;
186- projection . scale ( fitScale ) ;
187- } else {
188- projection . scale ( scale ) ;
189- }
190-
191- return projection ;
192- }
193-
194- if ( rotate ) {
195- projection . rotate ?.( rotate ) ;
196- }
197-
198- if ( scale ) {
199- projection . scale ( scale ) ;
200- projection . clipExtent ?.( [
201- [ drawingArea . left , drawingArea . top ] ,
202- [ drawingArea . left + drawingArea . width , drawingArea . top + drawingArea . height ] ,
203- ] ) ;
204- } else {
205- projection . fitExtent ?.(
206- [
207- [ drawingArea . left , drawingArea . top ] ,
208- [ drawingArea . left + drawingArea . width , drawingArea . top + drawingArea . height ] ,
209- ] ,
210- geoData ,
211- ) ;
212- }
213-
214- projection . translate (
215- translate ?? [
216- drawingArea . left + drawingArea . width / 2 ,
217- drawingArea . top + drawingArea . height / 2 ,
218- ] ,
219- ) ;
220- }
221- return projection ;
222- } ,
223- ) ;
224-
225- /**
226- * Resolves the raw `projection` input into a ready-to-use `GeoPath` instance
227- * fitted to the chart's drawing area.
228- */
229- export const selectorChartGeoPath = createSelectorMemoized (
230- selectorChartProjection ,
231- ( projection ) : GeoPath | null => {
232- if ( ! projection ) {
233- return null ;
234- }
235- return geoPath ( projection ) ;
236- } ,
237- ) ;
1+ import { useGeoProjectionSelectors } from '@mui/x-charts/internals' ;
2+
3+ export const selectorChartGeoFeatureIndexesByName = useGeoProjectionSelectors . selectorChartGeoFeatureIndexesByName ;
4+ export const selectorChartGeoProjectionState = useGeoProjectionSelectors . selectorChartGeoProjectionState ;
5+ export const selectorChartGeoData = useGeoProjectionSelectors . selectorChartGeoData ;
6+ export const selectorChartRawProjection = useGeoProjectionSelectors . selectorChartRawProjection ;
7+ export const selectorChartRawScale = useGeoProjectionSelectors . selectorChartRawScale ;
8+ export const selectorChartProjection = useGeoProjectionSelectors . selectorChartProjection ;
9+ export const selectorChartGeoPath = useGeoProjectionSelectors . selectorChartGeoPath ;
0 commit comments