source: node_modules/recharts/es6/state/selectors/axisSelectors.js

Last change on this file was a762898, checked in by istevanoska <ilinastevanoska@…>, 5 months ago

Added visualizations

  • Property mode set to 100644
File size: 52.8 KB
Line 
1function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6import { createSelector } from 'reselect';
7import range from 'es-toolkit/compat/range';
8import * as d3Scales from 'victory-vendor/d3-scale';
9import { selectChartLayout } from '../../context/chartLayoutContext';
10import { getDomainOfStackGroups, getStackedData, getValueByDataKey, isCategoricalAxis } from '../../util/ChartUtils';
11import { selectChartDataWithIndexes, selectChartDataWithIndexesIfNotInPanoramaPosition4 } from './dataSelectors';
12import { isWellFormedNumberDomain, numericalDomainSpecifiedWithoutRequiringData, parseNumericalUserDomain } from '../../util/isDomainSpecifiedByUser';
13import { getPercentValue, hasDuplicate, isNan, isNotNil, isNumOrStr, mathSign, upperFirst } from '../../util/DataUtils';
14import { isWellBehavedNumber } from '../../util/isWellBehavedNumber';
15import { getNiceTickValues, getTickValuesFixedDomain } from '../../util/scale';
16import { selectChartHeight, selectChartWidth } from './containerSelectors';
17import { selectAllXAxes, selectAllYAxes } from './selectAllAxes';
18import { selectChartOffsetInternal } from './selectChartOffsetInternal';
19import { selectBrushDimensions, selectBrushSettings } from './brushSelectors';
20import { selectBarCategoryGap, selectChartName, selectReverseStackOrder, selectStackOffsetType } from './rootPropsSelectors';
21import { selectAngleAxis, selectAngleAxisRange, selectRadiusAxis, selectRadiusAxisRange } from './polarAxisSelectors';
22import { pickAxisType } from './pickAxisType';
23import { pickAxisId } from './pickAxisId';
24import { combineAxisRangeWithReverse } from './combiners/combineAxisRangeWithReverse';
25import { DEFAULT_Y_AXIS_WIDTH } from '../../util/Constants';
26import { getStackSeriesIdentifier } from '../../util/stacks/getStackSeriesIdentifier';
27import { combineDisplayedStackedData } from './combiners/combineDisplayedStackedData';
28import { isStacked } from '../types/StackedGraphicalItem';
29import { numberDomainEqualityCheck } from './numberDomainEqualityCheck';
30import { emptyArraysAreEqualCheck } from './arrayEqualityCheck';
31import { selectTooltipAxisType } from './selectTooltipAxisType';
32import { selectTooltipAxisId } from './selectTooltipAxisId';
33import { rechartsScaleFactory } from '../../util/scale/RechartsScale';
34import { combineCheckedDomain } from './combiners/combineCheckedDomain';
35export var defaultNumericDomain = [0, 'auto'];
36/**
37 * If an axis is not explicitly defined as an element,
38 * we still need to render something in the chart and we need
39 * some object to hold the domain and default settings.
40 */
41export var implicitXAxis = {
42 allowDataOverflow: false,
43 allowDecimals: true,
44 allowDuplicatedCategory: true,
45 angle: 0,
46 dataKey: undefined,
47 domain: undefined,
48 height: 30,
49 hide: true,
50 id: 0,
51 includeHidden: false,
52 interval: 'preserveEnd',
53 minTickGap: 5,
54 mirror: false,
55 name: undefined,
56 orientation: 'bottom',
57 padding: {
58 left: 0,
59 right: 0
60 },
61 reversed: false,
62 scale: 'auto',
63 tick: true,
64 tickCount: 5,
65 tickFormatter: undefined,
66 ticks: undefined,
67 type: 'category',
68 unit: undefined
69};
70export var selectXAxisSettingsNoDefaults = (state, axisId) => {
71 return state.cartesianAxis.xAxis[axisId];
72};
73export var selectXAxisSettings = (state, axisId) => {
74 var axis = selectXAxisSettingsNoDefaults(state, axisId);
75 if (axis == null) {
76 return implicitXAxis;
77 }
78 return axis;
79};
80
81/**
82 * If an axis is not explicitly defined as an element,
83 * we still need to render something in the chart and we need
84 * some object to hold the domain and default settings.
85 */
86export var implicitYAxis = {
87 allowDataOverflow: false,
88 allowDecimals: true,
89 allowDuplicatedCategory: true,
90 angle: 0,
91 dataKey: undefined,
92 domain: defaultNumericDomain,
93 hide: true,
94 id: 0,
95 includeHidden: false,
96 interval: 'preserveEnd',
97 minTickGap: 5,
98 mirror: false,
99 name: undefined,
100 orientation: 'left',
101 padding: {
102 top: 0,
103 bottom: 0
104 },
105 reversed: false,
106 scale: 'auto',
107 tick: true,
108 tickCount: 5,
109 tickFormatter: undefined,
110 ticks: undefined,
111 type: 'number',
112 unit: undefined,
113 width: DEFAULT_Y_AXIS_WIDTH
114};
115export var selectYAxisSettingsNoDefaults = (state, axisId) => {
116 return state.cartesianAxis.yAxis[axisId];
117};
118export var selectYAxisSettings = (state, axisId) => {
119 var axis = selectYAxisSettingsNoDefaults(state, axisId);
120 if (axis == null) {
121 return implicitYAxis;
122 }
123 return axis;
124};
125export var implicitZAxis = {
126 domain: [0, 'auto'],
127 includeHidden: false,
128 reversed: false,
129 allowDataOverflow: false,
130 allowDuplicatedCategory: false,
131 dataKey: undefined,
132 id: 0,
133 name: '',
134 range: [64, 64],
135 scale: 'auto',
136 type: 'number',
137 unit: ''
138};
139export var selectZAxisSettings = (state, axisId) => {
140 var axis = state.cartesianAxis.zAxis[axisId];
141 if (axis == null) {
142 return implicitZAxis;
143 }
144 return axis;
145};
146export var selectBaseAxis = (state, axisType, axisId) => {
147 switch (axisType) {
148 case 'xAxis':
149 {
150 return selectXAxisSettings(state, axisId);
151 }
152 case 'yAxis':
153 {
154 return selectYAxisSettings(state, axisId);
155 }
156 case 'zAxis':
157 {
158 return selectZAxisSettings(state, axisId);
159 }
160 case 'angleAxis':
161 {
162 return selectAngleAxis(state, axisId);
163 }
164 case 'radiusAxis':
165 {
166 return selectRadiusAxis(state, axisId);
167 }
168 default:
169 throw new Error("Unexpected axis type: ".concat(axisType));
170 }
171};
172var selectCartesianAxisSettings = (state, axisType, axisId) => {
173 switch (axisType) {
174 case 'xAxis':
175 {
176 return selectXAxisSettings(state, axisId);
177 }
178 case 'yAxis':
179 {
180 return selectYAxisSettings(state, axisId);
181 }
182 default:
183 throw new Error("Unexpected axis type: ".concat(axisType));
184 }
185};
186
187/**
188 * Selects either an X or Y axis. Doesn't work with Z axis - for that, instead use selectBaseAxis.
189 * @param state Root state
190 * @param axisType xAxis | yAxis
191 * @param axisId xAxisId | yAxisId
192 * @returns axis settings object
193 */
194export var selectRenderableAxisSettings = (state, axisType, axisId) => {
195 switch (axisType) {
196 case 'xAxis':
197 {
198 return selectXAxisSettings(state, axisId);
199 }
200 case 'yAxis':
201 {
202 return selectYAxisSettings(state, axisId);
203 }
204 case 'angleAxis':
205 {
206 return selectAngleAxis(state, axisId);
207 }
208 case 'radiusAxis':
209 {
210 return selectRadiusAxis(state, axisId);
211 }
212 default:
213 throw new Error("Unexpected axis type: ".concat(axisType));
214 }
215};
216
217/**
218 * @param state RechartsRootState
219 * @return boolean true if there is at least one Bar or RadialBar
220 */
221export var selectHasBar = state => state.graphicalItems.cartesianItems.some(item => item.type === 'bar') || state.graphicalItems.polarItems.some(item => item.type === 'radialBar');
222
223/**
224 * Filters CartesianGraphicalItemSettings by the relevant axis ID
225 * @param axisType 'xAxis' | 'yAxis' | 'zAxis' | 'radiusAxis' | 'angleAxis'
226 * @param axisId from props, defaults to 0
227 *
228 * @returns Predicate function that return true for CartesianGraphicalItemSettings that are relevant to the specified axis
229 */
230export function itemAxisPredicate(axisType, axisId) {
231 return item => {
232 switch (axisType) {
233 case 'xAxis':
234 // This is sensitive to the data type, as 0 !== '0'. I wonder if we should be more flexible. How does 2.x branch behave? TODO write test for that
235 return 'xAxisId' in item && item.xAxisId === axisId;
236 case 'yAxis':
237 return 'yAxisId' in item && item.yAxisId === axisId;
238 case 'zAxis':
239 return 'zAxisId' in item && item.zAxisId === axisId;
240 case 'angleAxis':
241 return 'angleAxisId' in item && item.angleAxisId === axisId;
242 case 'radiusAxis':
243 return 'radiusAxisId' in item && item.radiusAxisId === axisId;
244 default:
245 return false;
246 }
247 };
248}
249
250// TODO appears there is a bug where this selector is called from polar context, find and fix it.
251export var selectUnfilteredCartesianItems = state => state.graphicalItems.cartesianItems;
252var selectAxisPredicate = createSelector([pickAxisType, pickAxisId], itemAxisPredicate);
253export var combineGraphicalItemsSettings = (graphicalItems, axisSettings, axisPredicate) => graphicalItems.filter(axisPredicate).filter(item => {
254 if ((axisSettings === null || axisSettings === void 0 ? void 0 : axisSettings.includeHidden) === true) {
255 return true;
256 }
257 return !item.hide;
258});
259export var selectCartesianItemsSettings = createSelector([selectUnfilteredCartesianItems, selectBaseAxis, selectAxisPredicate], combineGraphicalItemsSettings, {
260 memoizeOptions: {
261 resultEqualityCheck: emptyArraysAreEqualCheck
262 }
263});
264export var selectStackedCartesianItemsSettings = createSelector([selectCartesianItemsSettings], cartesianItems => {
265 return cartesianItems.filter(item => item.type === 'area' || item.type === 'bar').filter(isStacked);
266});
267export var filterGraphicalNotStackedItems = cartesianItems => cartesianItems.filter(item => !('stackId' in item) || item.stackId === undefined);
268var selectCartesianItemsSettingsExceptStacked = createSelector([selectCartesianItemsSettings], filterGraphicalNotStackedItems);
269export var combineGraphicalItemsData = cartesianItems => cartesianItems.map(item => item.data).filter(Boolean).flat(1);
270
271/**
272 * This is a "cheap" selector - it returns the data but doesn't iterate them, so it is not sensitive on the array length.
273 * Also does not apply dataKey yet.
274 * @param state RechartsRootState
275 * @returns data defined on the chart graphical items, such as Line or Scatter or Pie, and filtered with appropriate dataKey
276 */
277export var selectCartesianGraphicalItemsData = createSelector([selectCartesianItemsSettings], combineGraphicalItemsData, {
278 memoizeOptions: {
279 resultEqualityCheck: emptyArraysAreEqualCheck
280 }
281});
282export var combineDisplayedData = (graphicalItemsData, _ref) => {
283 var {
284 chartData = [],
285 dataStartIndex,
286 dataEndIndex
287 } = _ref;
288 if (graphicalItemsData.length > 0) {
289 /*
290 * There is no slicing when data is defined on graphical items. Why?
291 * Because Brush ignores data defined on graphical items,
292 * and does not render.
293 * So Brush will never show up in a Scatter chart for example.
294 * This is something we will need to fix.
295 *
296 * Now, when the root chart data is not defined, the dataEndIndex is 0,
297 * which means the itemsData will be sliced to an empty array anyway.
298 * But that's an implementation detail, and we can fix that too.
299 *
300 * Also, in absence of Axis dataKey, we use the dataKey from each item, respectively.
301 * This is the usual pattern for numerical axis, that is the one where bars go up:
302 * users don't specify any dataKey by default and expect the axis to "just match the data".
303 */
304 return graphicalItemsData;
305 }
306 return chartData.slice(dataStartIndex, dataEndIndex + 1);
307};
308
309/**
310 * This selector will return all data there is in the chart: graphical items, chart root, all together.
311 * Useful for figuring out an axis domain (because that needs to know of everything),
312 * not useful for rendering individual graphical elements (because they need to know which data is theirs and which is not).
313 *
314 * This function will discard the original indexes, so it is also not useful for anything that depends on ordering.
315 */
316export var selectDisplayedData = createSelector([selectCartesianGraphicalItemsData, selectChartDataWithIndexesIfNotInPanoramaPosition4], combineDisplayedData);
317export var combineAppliedValues = (data, axisSettings, items) => {
318 if ((axisSettings === null || axisSettings === void 0 ? void 0 : axisSettings.dataKey) != null) {
319 return data.map(item => ({
320 value: getValueByDataKey(item, axisSettings.dataKey)
321 }));
322 }
323 if (items.length > 0) {
324 return items.map(item => item.dataKey).flatMap(dataKey => data.map(entry => ({
325 value: getValueByDataKey(entry, dataKey)
326 })));
327 }
328 return data.map(entry => ({
329 value: entry
330 }));
331};
332
333/**
334 * This selector will return all values with the appropriate dataKey applied on them.
335 * Which dataKey is appropriate depends on where it is defined.
336 *
337 * This is an expensive selector - it will iterate all data and compute their value using the provided dataKey.
338 */
339export var selectAllAppliedValues = createSelector([selectDisplayedData, selectBaseAxis, selectCartesianItemsSettings], combineAppliedValues);
340export function isErrorBarRelevantForAxisType(axisType, errorBar) {
341 switch (axisType) {
342 case 'xAxis':
343 return errorBar.direction === 'x';
344 case 'yAxis':
345 return errorBar.direction === 'y';
346 default:
347 return false;
348 }
349}
350function makeNumber(val) {
351 if (isNumOrStr(val) || val instanceof Date) {
352 var n = Number(val);
353 if (isWellBehavedNumber(n)) {
354 return n;
355 }
356 }
357 return undefined;
358}
359function makeDomain(val) {
360 if (Array.isArray(val)) {
361 var attempt = [makeNumber(val[0]), makeNumber(val[1])];
362 if (isWellFormedNumberDomain(attempt)) {
363 return attempt;
364 }
365 return undefined;
366 }
367 var n = makeNumber(val);
368 if (n == null) {
369 return undefined;
370 }
371 return [n, n];
372}
373function onlyAllowNumbers(data) {
374 return data.map(makeNumber).filter(isNotNil);
375}
376
377/**
378 * @param entry One item in the 'data' array. Could be anything really - this is defined externally. This is the raw, before dataKey application
379 * @param appliedValue This is the result of applying the 'main' dataKey on the `entry`.
380 * @param relevantErrorBars Error bars that are relevant for the current axis and layout and all that.
381 * @return either undefined or an array of ErrorValue
382 */
383export function getErrorDomainByDataKey(entry, appliedValue, relevantErrorBars) {
384 if (!relevantErrorBars || typeof appliedValue !== 'number' || isNan(appliedValue)) {
385 return [];
386 }
387 if (!relevantErrorBars.length) {
388 return [];
389 }
390 return onlyAllowNumbers(relevantErrorBars.flatMap(eb => {
391 var errorValue = getValueByDataKey(entry, eb.dataKey);
392 var lowBound, highBound;
393 if (Array.isArray(errorValue)) {
394 [lowBound, highBound] = errorValue;
395 } else {
396 lowBound = highBound = errorValue;
397 }
398 if (!isWellBehavedNumber(lowBound) || !isWellBehavedNumber(highBound)) {
399 return undefined;
400 }
401 return [appliedValue - lowBound, appliedValue + highBound];
402 }));
403}
404export var selectTooltipAxis = state => {
405 var axisType = selectTooltipAxisType(state);
406 var axisId = selectTooltipAxisId(state);
407 return selectRenderableAxisSettings(state, axisType, axisId);
408};
409export var selectTooltipAxisDataKey = createSelector([selectTooltipAxis], axis => axis === null || axis === void 0 ? void 0 : axis.dataKey);
410export var selectDisplayedStackedData = createSelector([selectStackedCartesianItemsSettings, selectChartDataWithIndexesIfNotInPanoramaPosition4, selectTooltipAxis], combineDisplayedStackedData);
411export var combineStackGroups = (displayedData, items, stackOffsetType, reverseStackOrder) => {
412 var initialItemsGroups = {};
413 var itemsGroup = items.reduce((acc, item) => {
414 if (item.stackId == null) {
415 return acc;
416 }
417 var stack = acc[item.stackId];
418 if (stack == null) {
419 stack = [];
420 }
421 stack.push(item);
422 acc[item.stackId] = stack;
423 return acc;
424 }, initialItemsGroups);
425 return Object.fromEntries(Object.entries(itemsGroup).map(_ref2 => {
426 var [stackId, graphicalItems] = _ref2;
427 var orderedGraphicalItems = reverseStackOrder ? [...graphicalItems].reverse() : graphicalItems;
428 var dataKeys = orderedGraphicalItems.map(getStackSeriesIdentifier);
429 return [stackId, {
430 // @ts-expect-error getStackedData requires that the input is array of objects, Recharts does not test for that
431 stackedData: getStackedData(displayedData, dataKeys, stackOffsetType),
432 graphicalItems: orderedGraphicalItems
433 }];
434 }));
435};
436
437/**
438 * Stack groups are groups of graphical items that stack on each other.
439 * Stack is a function of axis type (X, Y), axis ID, and stack ID.
440 * Graphical items that do not have a stack ID are not going to be present in stack groups.
441 */
442export var selectStackGroups = createSelector([selectDisplayedStackedData, selectStackedCartesianItemsSettings, selectStackOffsetType, selectReverseStackOrder], combineStackGroups);
443export var combineDomainOfStackGroups = (stackGroups, _ref3, axisType, domainFromUserPreference) => {
444 var {
445 dataStartIndex,
446 dataEndIndex
447 } = _ref3;
448 if (domainFromUserPreference != null) {
449 // User has specified a domain, so we respect that and we can skip computing anything else
450 return undefined;
451 }
452 if (axisType === 'zAxis') {
453 // ZAxis ignores stacks
454 return undefined;
455 }
456 var domainOfStackGroups = getDomainOfStackGroups(stackGroups, dataStartIndex, dataEndIndex);
457 if (domainOfStackGroups != null && domainOfStackGroups[0] === 0 && domainOfStackGroups[1] === 0) {
458 return undefined;
459 }
460 return domainOfStackGroups;
461};
462var selectAllowsDataOverflow = createSelector([selectBaseAxis], axisSettings => axisSettings.allowDataOverflow);
463export var getDomainDefinition = axisSettings => {
464 var _axisSettings$domain;
465 if (axisSettings == null || !('domain' in axisSettings)) {
466 return defaultNumericDomain;
467 }
468 if (axisSettings.domain != null) {
469 return axisSettings.domain;
470 }
471 if ('ticks' in axisSettings && axisSettings.ticks != null) {
472 if (axisSettings.type === 'number') {
473 var allValues = onlyAllowNumbers(axisSettings.ticks);
474 return [Math.min(...allValues), Math.max(...allValues)];
475 }
476 if (axisSettings.type === 'category') {
477 return axisSettings.ticks.map(String);
478 }
479 }
480 return (_axisSettings$domain = axisSettings === null || axisSettings === void 0 ? void 0 : axisSettings.domain) !== null && _axisSettings$domain !== void 0 ? _axisSettings$domain : defaultNumericDomain;
481};
482export var selectDomainDefinition = createSelector([selectBaseAxis], getDomainDefinition);
483
484/**
485 * Under certain circumstances, we can determine the domain without looking at the data at all.
486 * This is the case when the domain is explicitly specified as numbers, or when it is specified
487 * as 'auto' or 'dataMin'/'dataMax' and data overflow is not allowed.
488 *
489 * In that case, this function will return the domain, otherwise it returns undefined.
490 *
491 * This is an optimization to avoid unnecessary data processing.
492 * @param state
493 * @param axisType
494 * @param axisId
495 * @param isPanorama
496 */
497export var selectDomainFromUserPreference = createSelector([selectDomainDefinition, selectAllowsDataOverflow], numericalDomainSpecifiedWithoutRequiringData);
498export var selectDomainOfStackGroups = createSelector([selectStackGroups, selectChartDataWithIndexes, pickAxisType, selectDomainFromUserPreference], combineDomainOfStackGroups, {
499 memoizeOptions: {
500 resultEqualityCheck: numberDomainEqualityCheck
501 }
502});
503export var selectAllErrorBarSettings = state => state.errorBars;
504var combineRelevantErrorBarSettings = (cartesianItemsSettings, allErrorBarSettings, axisType) => {
505 return cartesianItemsSettings.flatMap(item => {
506 return allErrorBarSettings[item.id];
507 }).filter(Boolean).filter(e => {
508 return isErrorBarRelevantForAxisType(axisType, e);
509 });
510};
511export var mergeDomains = function mergeDomains() {
512 for (var _len = arguments.length, domains = new Array(_len), _key = 0; _key < _len; _key++) {
513 domains[_key] = arguments[_key];
514 }
515 var allDomains = domains.filter(Boolean);
516 if (allDomains.length === 0) {
517 return undefined;
518 }
519 var allValues = allDomains.flat();
520 var min = Math.min(...allValues);
521 var max = Math.max(...allValues);
522 return [min, max];
523};
524export var combineDomainOfAllAppliedNumericalValuesIncludingErrorValues = (data, axisSettings, items, errorBars, axisType) => {
525 var lowerEnd, upperEnd;
526 if (items.length > 0) {
527 data.forEach(entry => {
528 items.forEach(item => {
529 var _errorBars$item$id, _axisSettings$dataKey;
530 var relevantErrorBars = (_errorBars$item$id = errorBars[item.id]) === null || _errorBars$item$id === void 0 ? void 0 : _errorBars$item$id.filter(errorBar => isErrorBarRelevantForAxisType(axisType, errorBar));
531 var valueByDataKey = getValueByDataKey(entry, (_axisSettings$dataKey = axisSettings.dataKey) !== null && _axisSettings$dataKey !== void 0 ? _axisSettings$dataKey : item.dataKey);
532 var errorDomain = getErrorDomainByDataKey(entry, valueByDataKey, relevantErrorBars);
533 if (errorDomain.length >= 2) {
534 var localLower = Math.min(...errorDomain);
535 var localUpper = Math.max(...errorDomain);
536 if (lowerEnd == null || localLower < lowerEnd) {
537 lowerEnd = localLower;
538 }
539 if (upperEnd == null || localUpper > upperEnd) {
540 upperEnd = localUpper;
541 }
542 }
543 var dataValueDomain = makeDomain(valueByDataKey);
544 if (dataValueDomain != null) {
545 lowerEnd = lowerEnd == null ? dataValueDomain[0] : Math.min(lowerEnd, dataValueDomain[0]);
546 upperEnd = upperEnd == null ? dataValueDomain[1] : Math.max(upperEnd, dataValueDomain[1]);
547 }
548 });
549 });
550 }
551 if ((axisSettings === null || axisSettings === void 0 ? void 0 : axisSettings.dataKey) != null) {
552 data.forEach(item => {
553 var dataValueDomain = makeDomain(getValueByDataKey(item, axisSettings.dataKey));
554 if (dataValueDomain != null) {
555 lowerEnd = lowerEnd == null ? dataValueDomain[0] : Math.min(lowerEnd, dataValueDomain[0]);
556 upperEnd = upperEnd == null ? dataValueDomain[1] : Math.max(upperEnd, dataValueDomain[1]);
557 }
558 });
559 }
560 if (isWellBehavedNumber(lowerEnd) && isWellBehavedNumber(upperEnd)) {
561 return [lowerEnd, upperEnd];
562 }
563 return undefined;
564};
565var selectDomainOfAllAppliedNumericalValuesIncludingErrorValues = createSelector([selectDisplayedData, selectBaseAxis, selectCartesianItemsSettingsExceptStacked, selectAllErrorBarSettings, pickAxisType], combineDomainOfAllAppliedNumericalValuesIncludingErrorValues, {
566 memoizeOptions: {
567 resultEqualityCheck: numberDomainEqualityCheck
568 }
569});
570function onlyAllowNumbersAndStringsAndDates(item) {
571 var {
572 value
573 } = item;
574 if (isNumOrStr(value) || value instanceof Date) {
575 return value;
576 }
577 return undefined;
578}
579var computeDomainOfTypeCategory = (allDataSquished, axisSettings, isCategorical) => {
580 var categoricalDomain = allDataSquished.map(onlyAllowNumbersAndStringsAndDates).filter(v => v != null);
581 if (isCategorical && (axisSettings.dataKey == null || axisSettings.allowDuplicatedCategory && hasDuplicate(categoricalDomain))) {
582 /*
583 * 1. In an absence of dataKey, Recharts will use array indexes as its categorical domain
584 * 2. When category axis has duplicated text, serial numbers are used to generate scale
585 */
586 return range(0, allDataSquished.length);
587 }
588 if (axisSettings.allowDuplicatedCategory) {
589 return categoricalDomain;
590 }
591 return Array.from(new Set(categoricalDomain));
592};
593export var selectReferenceDots = state => state.referenceElements.dots;
594export var filterReferenceElements = (elements, axisType, axisId) => {
595 return elements.filter(el => el.ifOverflow === 'extendDomain').filter(el => {
596 if (axisType === 'xAxis') {
597 return el.xAxisId === axisId;
598 }
599 return el.yAxisId === axisId;
600 });
601};
602export var selectReferenceDotsByAxis = createSelector([selectReferenceDots, pickAxisType, pickAxisId], filterReferenceElements);
603export var selectReferenceAreas = state => state.referenceElements.areas;
604export var selectReferenceAreasByAxis = createSelector([selectReferenceAreas, pickAxisType, pickAxisId], filterReferenceElements);
605export var selectReferenceLines = state => state.referenceElements.lines;
606export var selectReferenceLinesByAxis = createSelector([selectReferenceLines, pickAxisType, pickAxisId], filterReferenceElements);
607export var combineDotsDomain = (dots, axisType) => {
608 if (dots == null) {
609 return undefined;
610 }
611 var allCoords = onlyAllowNumbers(dots.map(dot => axisType === 'xAxis' ? dot.x : dot.y));
612 if (allCoords.length === 0) {
613 return undefined;
614 }
615 return [Math.min(...allCoords), Math.max(...allCoords)];
616};
617var selectReferenceDotsDomain = createSelector(selectReferenceDotsByAxis, pickAxisType, combineDotsDomain);
618export var combineAreasDomain = (areas, axisType) => {
619 if (areas == null) {
620 return undefined;
621 }
622 var allCoords = onlyAllowNumbers(areas.flatMap(area => [axisType === 'xAxis' ? area.x1 : area.y1, axisType === 'xAxis' ? area.x2 : area.y2]));
623 if (allCoords.length === 0) {
624 return undefined;
625 }
626 return [Math.min(...allCoords), Math.max(...allCoords)];
627};
628var selectReferenceAreasDomain = createSelector([selectReferenceAreasByAxis, pickAxisType], combineAreasDomain);
629function extractXCoordinates(line) {
630 var _line$segment;
631 if (line.x != null) {
632 return onlyAllowNumbers([line.x]);
633 }
634 var segmentCoordinates = (_line$segment = line.segment) === null || _line$segment === void 0 ? void 0 : _line$segment.map(s => s.x);
635 if (segmentCoordinates == null || segmentCoordinates.length === 0) {
636 return [];
637 }
638 return onlyAllowNumbers(segmentCoordinates);
639}
640function extractYCoordinates(line) {
641 var _line$segment2;
642 if (line.y != null) {
643 return onlyAllowNumbers([line.y]);
644 }
645 var segmentCoordinates = (_line$segment2 = line.segment) === null || _line$segment2 === void 0 ? void 0 : _line$segment2.map(s => s.y);
646 if (segmentCoordinates == null || segmentCoordinates.length === 0) {
647 return [];
648 }
649 return onlyAllowNumbers(segmentCoordinates);
650}
651export var combineLinesDomain = (lines, axisType) => {
652 if (lines == null) {
653 return undefined;
654 }
655 var allCoords = lines.flatMap(line => axisType === 'xAxis' ? extractXCoordinates(line) : extractYCoordinates(line));
656 if (allCoords.length === 0) {
657 return undefined;
658 }
659 return [Math.min(...allCoords), Math.max(...allCoords)];
660};
661var selectReferenceLinesDomain = createSelector([selectReferenceLinesByAxis, pickAxisType], combineLinesDomain);
662var selectReferenceElementsDomain = createSelector(selectReferenceDotsDomain, selectReferenceLinesDomain, selectReferenceAreasDomain, (dotsDomain, linesDomain, areasDomain) => {
663 return mergeDomains(dotsDomain, areasDomain, linesDomain);
664});
665export var combineNumericalDomain = (axisSettings, domainDefinition, domainFromUserPreference, domainOfStackGroups, dataAndErrorBarsDomain, referenceElementsDomain, layout, axisType) => {
666 if (domainFromUserPreference != null) {
667 // We're done! No need to compute anything else.
668 return domainFromUserPreference;
669 }
670 var shouldIncludeDomainOfStackGroups = layout === 'vertical' && axisType === 'xAxis' || layout === 'horizontal' && axisType === 'yAxis';
671 var mergedDomains = shouldIncludeDomainOfStackGroups ? mergeDomains(domainOfStackGroups, referenceElementsDomain, dataAndErrorBarsDomain) : mergeDomains(referenceElementsDomain, dataAndErrorBarsDomain);
672 return parseNumericalUserDomain(domainDefinition, mergedDomains, axisSettings.allowDataOverflow);
673};
674export var selectNumericalDomain = createSelector([selectBaseAxis, selectDomainDefinition, selectDomainFromUserPreference, selectDomainOfStackGroups, selectDomainOfAllAppliedNumericalValuesIncludingErrorValues, selectReferenceElementsDomain, selectChartLayout, pickAxisType], combineNumericalDomain, {
675 memoizeOptions: {
676 resultEqualityCheck: numberDomainEqualityCheck
677 }
678});
679
680/**
681 * Expand by design maps everything between 0 and 1,
682 * there is nothing to compute.
683 * See https://d3js.org/d3-shape/stack#stack-offsets
684 */
685var expandDomain = [0, 1];
686export var combineAxisDomain = (axisSettings, layout, displayedData, allAppliedValues, stackOffsetType, axisType, numericalDomain) => {
687 if ((axisSettings == null || displayedData == null || displayedData.length === 0) && numericalDomain === undefined) {
688 return undefined;
689 }
690 var {
691 dataKey,
692 type
693 } = axisSettings;
694 var isCategorical = isCategoricalAxis(layout, axisType);
695 if (isCategorical && dataKey == null) {
696 var _displayedData$length;
697 return range(0, (_displayedData$length = displayedData === null || displayedData === void 0 ? void 0 : displayedData.length) !== null && _displayedData$length !== void 0 ? _displayedData$length : 0);
698 }
699 if (type === 'category') {
700 return computeDomainOfTypeCategory(allAppliedValues, axisSettings, isCategorical);
701 }
702 if (stackOffsetType === 'expand') {
703 return expandDomain;
704 }
705 return numericalDomain;
706};
707export var selectAxisDomain = createSelector([selectBaseAxis, selectChartLayout, selectDisplayedData, selectAllAppliedValues, selectStackOffsetType, pickAxisType, selectNumericalDomain], combineAxisDomain);
708function isSupportedScaleName(name) {
709 return name in d3Scales;
710}
711export var combineRealScaleType = (axisConfig, hasBar, chartType) => {
712 if (axisConfig == null) {
713 return undefined;
714 }
715 var {
716 scale,
717 type
718 } = axisConfig;
719 if (scale === 'auto') {
720 if (type === 'category' && chartType && (chartType.indexOf('LineChart') >= 0 || chartType.indexOf('AreaChart') >= 0 || chartType.indexOf('ComposedChart') >= 0 && !hasBar)) {
721 return 'point';
722 }
723 if (type === 'category') {
724 return 'band';
725 }
726 return 'linear';
727 }
728 if (typeof scale === 'string') {
729 var name = "scale".concat(upperFirst(scale));
730 return isSupportedScaleName(name) ? name : 'point';
731 }
732 return undefined;
733};
734export var selectRealScaleType = createSelector([selectBaseAxis, selectHasBar, selectChartName], combineRealScaleType);
735export function combineScaleFunction(axis, realScaleType, axisDomain, axisRange) {
736 if (axisDomain == null || axisRange == null) {
737 return undefined;
738 }
739 if (typeof axis.scale === 'function') {
740 return rechartsScaleFactory(axis.scale, axisDomain, axisRange);
741 }
742 return rechartsScaleFactory(realScaleType, axisDomain, axisRange);
743}
744export var combineNiceTicks = (axisDomain, axisSettings, realScaleType) => {
745 var domainDefinition = getDomainDefinition(axisSettings);
746 if (realScaleType !== 'auto' && realScaleType !== 'linear') {
747 return undefined;
748 }
749 if (axisSettings != null && axisSettings.tickCount && Array.isArray(domainDefinition) && (domainDefinition[0] === 'auto' || domainDefinition[1] === 'auto') && isWellFormedNumberDomain(axisDomain)) {
750 return getNiceTickValues(axisDomain, axisSettings.tickCount, axisSettings.allowDecimals);
751 }
752 if (axisSettings != null && axisSettings.tickCount && axisSettings.type === 'number' && isWellFormedNumberDomain(axisDomain)) {
753 return getTickValuesFixedDomain(axisDomain, axisSettings.tickCount, axisSettings.allowDecimals);
754 }
755 return undefined;
756};
757export var selectNiceTicks = createSelector([selectAxisDomain, selectRenderableAxisSettings, selectRealScaleType], combineNiceTicks);
758export var combineAxisDomainWithNiceTicks = (axisSettings, domain, niceTicks, axisType) => {
759 if (
760 /*
761 * Angle axis for some reason uses nice ticks when rendering axis tick labels,
762 * but doesn't use nice ticks for extending domain like all the other axes do.
763 * Not really sure why? Is there a good reason,
764 * or is it just because someone added support for nice ticks to the other axes and forgot this one?
765 */
766 axisType !== 'angleAxis' && (axisSettings === null || axisSettings === void 0 ? void 0 : axisSettings.type) === 'number' && isWellFormedNumberDomain(domain) && Array.isArray(niceTicks) && niceTicks.length > 0) {
767 var _niceTicks$, _niceTicks;
768 var minFromDomain = domain[0];
769 var minFromTicks = (_niceTicks$ = niceTicks[0]) !== null && _niceTicks$ !== void 0 ? _niceTicks$ : 0;
770 var maxFromDomain = domain[1];
771 var maxFromTicks = (_niceTicks = niceTicks[niceTicks.length - 1]) !== null && _niceTicks !== void 0 ? _niceTicks : 0;
772 return [Math.min(minFromDomain, minFromTicks), Math.max(maxFromDomain, maxFromTicks)];
773 }
774 return domain;
775};
776export var selectAxisDomainIncludingNiceTicks = createSelector([selectBaseAxis, selectAxisDomain, selectNiceTicks, pickAxisType], combineAxisDomainWithNiceTicks);
777
778/**
779 * Returns the smallest gap, between two numbers in the data, as a ratio of the whole range (max - min).
780 * Ignores domain provided by user and only considers domain from data.
781 *
782 * The result is a number between 0 and 1.
783 */
784export var selectSmallestDistanceBetweenValues = createSelector(selectAllAppliedValues, selectBaseAxis, (allDataSquished, axisSettings) => {
785 if (!axisSettings || axisSettings.type !== 'number') {
786 return undefined;
787 }
788 var smallestDistanceBetweenValues = Infinity;
789 var sortedValues = Array.from(onlyAllowNumbers(allDataSquished.map(d => d.value))).sort((a, b) => a - b);
790 var first = sortedValues[0];
791 var last = sortedValues[sortedValues.length - 1];
792 if (first == null || last == null) {
793 return Infinity;
794 }
795 var diff = last - first;
796 if (diff === 0) {
797 return Infinity;
798 }
799 // Only do n - 1 distance calculations because there's only n - 1 distances between n values.
800 for (var i = 0; i < sortedValues.length - 1; i++) {
801 var curr = sortedValues[i];
802 var next = sortedValues[i + 1];
803 if (curr == null || next == null) {
804 continue;
805 }
806 var distance = next - curr;
807 smallestDistanceBetweenValues = Math.min(smallestDistanceBetweenValues, distance);
808 }
809 return smallestDistanceBetweenValues / diff;
810});
811var selectCalculatedPadding = createSelector(selectSmallestDistanceBetweenValues, selectChartLayout, selectBarCategoryGap, selectChartOffsetInternal, (_1, _2, _3, _4, padding) => padding, (smallestDistanceInPercent, layout, barCategoryGap, offset, padding) => {
812 if (!isWellBehavedNumber(smallestDistanceInPercent)) {
813 return 0;
814 }
815 var rangeWidth = layout === 'vertical' ? offset.height : offset.width;
816 if (padding === 'gap') {
817 return smallestDistanceInPercent * rangeWidth / 2;
818 }
819 if (padding === 'no-gap') {
820 var gap = getPercentValue(barCategoryGap, smallestDistanceInPercent * rangeWidth);
821 var halfBand = smallestDistanceInPercent * rangeWidth / 2;
822 return halfBand - gap - (halfBand - gap) / rangeWidth * gap;
823 }
824 return 0;
825});
826export var selectCalculatedXAxisPadding = (state, axisId, isPanorama) => {
827 var xAxisSettings = selectXAxisSettings(state, axisId);
828 if (xAxisSettings == null || typeof xAxisSettings.padding !== 'string') {
829 return 0;
830 }
831 return selectCalculatedPadding(state, 'xAxis', axisId, isPanorama, xAxisSettings.padding);
832};
833export var selectCalculatedYAxisPadding = (state, axisId, isPanorama) => {
834 var yAxisSettings = selectYAxisSettings(state, axisId);
835 if (yAxisSettings == null || typeof yAxisSettings.padding !== 'string') {
836 return 0;
837 }
838 return selectCalculatedPadding(state, 'yAxis', axisId, isPanorama, yAxisSettings.padding);
839};
840var selectXAxisPadding = createSelector(selectXAxisSettings, selectCalculatedXAxisPadding, (xAxisSettings, calculated) => {
841 var _padding$left, _padding$right;
842 if (xAxisSettings == null) {
843 return {
844 left: 0,
845 right: 0
846 };
847 }
848 var {
849 padding
850 } = xAxisSettings;
851 if (typeof padding === 'string') {
852 return {
853 left: calculated,
854 right: calculated
855 };
856 }
857 return {
858 left: ((_padding$left = padding.left) !== null && _padding$left !== void 0 ? _padding$left : 0) + calculated,
859 right: ((_padding$right = padding.right) !== null && _padding$right !== void 0 ? _padding$right : 0) + calculated
860 };
861});
862var selectYAxisPadding = createSelector(selectYAxisSettings, selectCalculatedYAxisPadding, (yAxisSettings, calculated) => {
863 var _padding$top, _padding$bottom;
864 if (yAxisSettings == null) {
865 return {
866 top: 0,
867 bottom: 0
868 };
869 }
870 var {
871 padding
872 } = yAxisSettings;
873 if (typeof padding === 'string') {
874 return {
875 top: calculated,
876 bottom: calculated
877 };
878 }
879 return {
880 top: ((_padding$top = padding.top) !== null && _padding$top !== void 0 ? _padding$top : 0) + calculated,
881 bottom: ((_padding$bottom = padding.bottom) !== null && _padding$bottom !== void 0 ? _padding$bottom : 0) + calculated
882 };
883});
884export var combineXAxisRange = createSelector([selectChartOffsetInternal, selectXAxisPadding, selectBrushDimensions, selectBrushSettings, (_state, _axisId, isPanorama) => isPanorama], (offset, padding, brushDimensions, _ref4, isPanorama) => {
885 var {
886 padding: brushPadding
887 } = _ref4;
888 if (isPanorama) {
889 return [brushPadding.left, brushDimensions.width - brushPadding.right];
890 }
891 return [offset.left + padding.left, offset.left + offset.width - padding.right];
892});
893export var combineYAxisRange = createSelector([selectChartOffsetInternal, selectChartLayout, selectYAxisPadding, selectBrushDimensions, selectBrushSettings, (_state, _axisId, isPanorama) => isPanorama], (offset, layout, padding, brushDimensions, _ref5, isPanorama) => {
894 var {
895 padding: brushPadding
896 } = _ref5;
897 if (isPanorama) {
898 return [brushDimensions.height - brushPadding.bottom, brushPadding.top];
899 }
900 if (layout === 'horizontal') {
901 return [offset.top + offset.height - padding.bottom, offset.top + padding.top];
902 }
903 return [offset.top + padding.top, offset.top + offset.height - padding.bottom];
904});
905export var selectAxisRange = (state, axisType, axisId, isPanorama) => {
906 var _selectZAxisSettings;
907 switch (axisType) {
908 case 'xAxis':
909 return combineXAxisRange(state, axisId, isPanorama);
910 case 'yAxis':
911 return combineYAxisRange(state, axisId, isPanorama);
912 case 'zAxis':
913 return (_selectZAxisSettings = selectZAxisSettings(state, axisId)) === null || _selectZAxisSettings === void 0 ? void 0 : _selectZAxisSettings.range;
914 case 'angleAxis':
915 return selectAngleAxisRange(state);
916 case 'radiusAxis':
917 return selectRadiusAxisRange(state, axisId);
918 default:
919 return undefined;
920 }
921};
922export var selectAxisRangeWithReverse = createSelector([selectBaseAxis, selectAxisRange], combineAxisRangeWithReverse);
923var selectCheckedAxisDomain = createSelector([selectRealScaleType, selectAxisDomainIncludingNiceTicks], combineCheckedDomain);
924export var selectAxisScale = createSelector([selectBaseAxis, selectRealScaleType, selectCheckedAxisDomain, selectAxisRangeWithReverse], combineScaleFunction);
925export var selectErrorBarsSettings = createSelector([selectCartesianItemsSettings, selectAllErrorBarSettings, pickAxisType], combineRelevantErrorBarSettings);
926function compareIds(a, b) {
927 if (a.id < b.id) {
928 return -1;
929 }
930 if (a.id > b.id) {
931 return 1;
932 }
933 return 0;
934}
935var pickAxisOrientation = (_state, orientation) => orientation;
936var pickMirror = (_state, _orientation, mirror) => mirror;
937var selectAllXAxesWithOffsetType = createSelector(selectAllXAxes, pickAxisOrientation, pickMirror, (allAxes, orientation, mirror) => allAxes.filter(axis => axis.orientation === orientation).filter(axis => axis.mirror === mirror).sort(compareIds));
938var selectAllYAxesWithOffsetType = createSelector(selectAllYAxes, pickAxisOrientation, pickMirror, (allAxes, orientation, mirror) => allAxes.filter(axis => axis.orientation === orientation).filter(axis => axis.mirror === mirror).sort(compareIds));
939var getXAxisSize = (offset, axisSettings) => {
940 return {
941 width: offset.width,
942 height: axisSettings.height
943 };
944};
945var getYAxisSize = (offset, axisSettings) => {
946 var width = typeof axisSettings.width === 'number' ? axisSettings.width : DEFAULT_Y_AXIS_WIDTH;
947 return {
948 width,
949 height: offset.height
950 };
951};
952export var selectXAxisSize = createSelector(selectChartOffsetInternal, selectXAxisSettings, getXAxisSize);
953var combineXAxisPositionStartingPoint = (offset, orientation, chartHeight) => {
954 switch (orientation) {
955 case 'top':
956 return offset.top;
957 case 'bottom':
958 return chartHeight - offset.bottom;
959 default:
960 return 0;
961 }
962};
963var combineYAxisPositionStartingPoint = (offset, orientation, chartWidth) => {
964 switch (orientation) {
965 case 'left':
966 return offset.left;
967 case 'right':
968 return chartWidth - offset.right;
969 default:
970 return 0;
971 }
972};
973export var selectAllXAxesOffsetSteps = createSelector(selectChartHeight, selectChartOffsetInternal, selectAllXAxesWithOffsetType, pickAxisOrientation, pickMirror, (chartHeight, offset, allAxesWithSameOffsetType, orientation, mirror) => {
974 var steps = {};
975 var position;
976 allAxesWithSameOffsetType.forEach(axis => {
977 var axisSize = getXAxisSize(offset, axis);
978 if (position == null) {
979 position = combineXAxisPositionStartingPoint(offset, orientation, chartHeight);
980 }
981 var needSpace = orientation === 'top' && !mirror || orientation === 'bottom' && mirror;
982 steps[axis.id] = position - Number(needSpace) * axisSize.height;
983 position += (needSpace ? -1 : 1) * axisSize.height;
984 });
985 return steps;
986});
987export var selectAllYAxesOffsetSteps = createSelector(selectChartWidth, selectChartOffsetInternal, selectAllYAxesWithOffsetType, pickAxisOrientation, pickMirror, (chartWidth, offset, allAxesWithSameOffsetType, orientation, mirror) => {
988 var steps = {};
989 var position;
990 allAxesWithSameOffsetType.forEach(axis => {
991 var axisSize = getYAxisSize(offset, axis);
992 if (position == null) {
993 position = combineYAxisPositionStartingPoint(offset, orientation, chartWidth);
994 }
995 var needSpace = orientation === 'left' && !mirror || orientation === 'right' && mirror;
996 steps[axis.id] = position - Number(needSpace) * axisSize.width;
997 position += (needSpace ? -1 : 1) * axisSize.width;
998 });
999 return steps;
1000});
1001var selectXAxisOffsetSteps = (state, axisId) => {
1002 var axisSettings = selectXAxisSettings(state, axisId);
1003 if (axisSettings == null) {
1004 return undefined;
1005 }
1006 return selectAllXAxesOffsetSteps(state, axisSettings.orientation, axisSettings.mirror);
1007};
1008export var selectXAxisPosition = createSelector([selectChartOffsetInternal, selectXAxisSettings, selectXAxisOffsetSteps, (_, axisId) => axisId], (offset, axisSettings, allSteps, axisId) => {
1009 if (axisSettings == null) {
1010 return undefined;
1011 }
1012 var stepOfThisAxis = allSteps === null || allSteps === void 0 ? void 0 : allSteps[axisId];
1013 if (stepOfThisAxis == null) {
1014 return {
1015 x: offset.left,
1016 y: 0
1017 };
1018 }
1019 return {
1020 x: offset.left,
1021 y: stepOfThisAxis
1022 };
1023});
1024var selectYAxisOffsetSteps = (state, axisId) => {
1025 var axisSettings = selectYAxisSettings(state, axisId);
1026 if (axisSettings == null) {
1027 return undefined;
1028 }
1029 return selectAllYAxesOffsetSteps(state, axisSettings.orientation, axisSettings.mirror);
1030};
1031export var selectYAxisPosition = createSelector([selectChartOffsetInternal, selectYAxisSettings, selectYAxisOffsetSteps, (_, axisId) => axisId], (offset, axisSettings, allSteps, axisId) => {
1032 if (axisSettings == null) {
1033 return undefined;
1034 }
1035 var stepOfThisAxis = allSteps === null || allSteps === void 0 ? void 0 : allSteps[axisId];
1036 if (stepOfThisAxis == null) {
1037 return {
1038 x: 0,
1039 y: offset.top
1040 };
1041 }
1042 return {
1043 x: stepOfThisAxis,
1044 y: offset.top
1045 };
1046});
1047export var selectYAxisSize = createSelector(selectChartOffsetInternal, selectYAxisSettings, (offset, axisSettings) => {
1048 var width = typeof axisSettings.width === 'number' ? axisSettings.width : DEFAULT_Y_AXIS_WIDTH;
1049 return {
1050 width,
1051 height: offset.height
1052 };
1053});
1054export var selectCartesianAxisSize = (state, axisType, axisId) => {
1055 switch (axisType) {
1056 case 'xAxis':
1057 {
1058 return selectXAxisSize(state, axisId).width;
1059 }
1060 case 'yAxis':
1061 {
1062 return selectYAxisSize(state, axisId).height;
1063 }
1064 default:
1065 {
1066 return undefined;
1067 }
1068 }
1069};
1070export var combineDuplicateDomain = (chartLayout, appliedValues, axis, axisType) => {
1071 if (axis == null) {
1072 return undefined;
1073 }
1074 var {
1075 allowDuplicatedCategory,
1076 type,
1077 dataKey
1078 } = axis;
1079 var isCategorical = isCategoricalAxis(chartLayout, axisType);
1080 var allData = appliedValues.map(av => av.value);
1081 if (dataKey && isCategorical && type === 'category' && allowDuplicatedCategory && hasDuplicate(allData)) {
1082 return allData;
1083 }
1084 return undefined;
1085};
1086export var selectDuplicateDomain = createSelector([selectChartLayout, selectAllAppliedValues, selectBaseAxis, pickAxisType], combineDuplicateDomain);
1087export var combineCategoricalDomain = (layout, appliedValues, axis, axisType) => {
1088 if (axis == null || axis.dataKey == null) {
1089 return undefined;
1090 }
1091 var {
1092 type,
1093 scale
1094 } = axis;
1095 var isCategorical = isCategoricalAxis(layout, axisType);
1096 if (isCategorical && (type === 'number' || scale !== 'auto')) {
1097 return appliedValues.map(d => d.value);
1098 }
1099 return undefined;
1100};
1101export var selectCategoricalDomain = createSelector([selectChartLayout, selectAllAppliedValues, selectRenderableAxisSettings, pickAxisType], combineCategoricalDomain);
1102export var selectAxisPropsNeededForCartesianGridTicksGenerator = createSelector([selectChartLayout, selectCartesianAxisSettings, selectRealScaleType, selectAxisScale, selectDuplicateDomain, selectCategoricalDomain, selectAxisRange, selectNiceTicks, pickAxisType], (layout, axis, realScaleType, scale, duplicateDomain, categoricalDomain, axisRange, niceTicks, axisType) => {
1103 if (axis == null) {
1104 return undefined;
1105 }
1106 var isCategorical = isCategoricalAxis(layout, axisType);
1107 return {
1108 angle: axis.angle,
1109 interval: axis.interval,
1110 minTickGap: axis.minTickGap,
1111 orientation: axis.orientation,
1112 tick: axis.tick,
1113 tickCount: axis.tickCount,
1114 tickFormatter: axis.tickFormatter,
1115 ticks: axis.ticks,
1116 type: axis.type,
1117 unit: axis.unit,
1118 axisType,
1119 categoricalDomain,
1120 duplicateDomain,
1121 isCategorical,
1122 niceTicks,
1123 range: axisRange,
1124 realScaleType,
1125 scale
1126 };
1127});
1128
1129/**
1130 * Of on four almost identical implementations of tick generation.
1131 * The four horsemen of tick generation are:
1132 * - {@link selectTooltipAxisTicks}
1133 * - {@link combineAxisTicks}
1134 * - {@link getTicksOfAxis}.
1135 * - {@link combineGraphicalItemTicks}
1136 */
1137export var combineAxisTicks = (layout, axis, realScaleType, scale, niceTicks, axisRange, duplicateDomain, categoricalDomain, axisType) => {
1138 if (axis == null || scale == null) {
1139 return undefined;
1140 }
1141 var isCategorical = isCategoricalAxis(layout, axisType);
1142 var {
1143 type,
1144 ticks,
1145 tickCount
1146 } = axis;
1147 var offsetForBand =
1148 // @ts-expect-error This is testing for `scaleBand` but for band axis the type is reported as `band` so this looks like a dead code with a workaround elsewhere?
1149 realScaleType === 'scaleBand' && typeof scale.bandwidth === 'function' ? scale.bandwidth() / 2 : 2;
1150 var offset = type === 'category' && scale.bandwidth ? scale.bandwidth() / offsetForBand : 0;
1151 offset = axisType === 'angleAxis' && axisRange != null && axisRange.length >= 2 ? mathSign(axisRange[0] - axisRange[1]) * 2 * offset : offset;
1152
1153 // The ticks set by user should only affect the ticks adjacent to axis line
1154 var ticksOrNiceTicks = ticks || niceTicks;
1155 if (ticksOrNiceTicks) {
1156 return ticksOrNiceTicks.map((entry, index) => {
1157 var scaleContent = duplicateDomain ? duplicateDomain.indexOf(entry) : entry;
1158 var scaled = scale.map(scaleContent);
1159 if (!isWellBehavedNumber(scaled)) {
1160 return null;
1161 }
1162 return {
1163 index,
1164 coordinate: scaled + offset,
1165 value: entry,
1166 offset
1167 };
1168 }).filter(isNotNil);
1169 }
1170
1171 // When axis is a categorical axis, but the type of axis is number or the scale of axis is not "auto"
1172 if (isCategorical && categoricalDomain) {
1173 return categoricalDomain.map((entry, index) => {
1174 var scaled = scale.map(entry);
1175 if (!isWellBehavedNumber(scaled)) {
1176 return null;
1177 }
1178 return {
1179 coordinate: scaled + offset,
1180 value: entry,
1181 index,
1182 offset
1183 };
1184 }).filter(isNotNil);
1185 }
1186 if (scale.ticks) {
1187 return scale.ticks(tickCount).map((entry, index) => {
1188 var scaled = scale.map(entry);
1189 if (!isWellBehavedNumber(scaled)) {
1190 return null;
1191 }
1192 return {
1193 coordinate: scaled + offset,
1194 value: entry,
1195 index,
1196 offset
1197 };
1198 }).filter(isNotNil);
1199 }
1200
1201 // When axis has duplicated text, serial numbers are used to generate scale
1202 return scale.domain().map((entry, index) => {
1203 var scaled = scale.map(entry);
1204 if (!isWellBehavedNumber(scaled)) {
1205 return null;
1206 }
1207 return {
1208 coordinate: scaled + offset,
1209 // @ts-expect-error can't use Date as index
1210 value: duplicateDomain ? duplicateDomain[entry] : entry,
1211 index,
1212 offset
1213 };
1214 }).filter(isNotNil);
1215};
1216export var selectTicksOfAxis = createSelector([selectChartLayout, selectRenderableAxisSettings, selectRealScaleType, selectAxisScale, selectNiceTicks, selectAxisRange, selectDuplicateDomain, selectCategoricalDomain, pickAxisType], combineAxisTicks);
1217
1218/**
1219 * Of on four almost identical implementations of tick generation.
1220 * The four horsemen of tick generation are:
1221 * - {@link selectTooltipAxisTicks}
1222 * - {@link combineAxisTicks}
1223 * - {@link getTicksOfAxis}.
1224 * - {@link combineGraphicalItemTicks}
1225 */
1226export var combineGraphicalItemTicks = (layout, axis, scale, axisRange, duplicateDomain, categoricalDomain, axisType) => {
1227 if (axis == null || scale == null || axisRange == null || axisRange[0] === axisRange[1]) {
1228 return undefined;
1229 }
1230 var isCategorical = isCategoricalAxis(layout, axisType);
1231 var {
1232 tickCount
1233 } = axis;
1234 var offset = 0;
1235 offset = axisType === 'angleAxis' && (axisRange === null || axisRange === void 0 ? void 0 : axisRange.length) >= 2 ? mathSign(axisRange[0] - axisRange[1]) * 2 * offset : offset;
1236
1237 // When axis is a categorical axis, but the type of axis is number or the scale of axis is not "auto"
1238 if (isCategorical && categoricalDomain) {
1239 return categoricalDomain.map((entry, index) => {
1240 var scaled = scale.map(entry);
1241 if (!isWellBehavedNumber(scaled)) {
1242 return null;
1243 }
1244 return {
1245 coordinate: scaled + offset,
1246 value: entry,
1247 index,
1248 offset
1249 };
1250 }).filter(isNotNil);
1251 }
1252 if (scale.ticks) {
1253 return scale.ticks(tickCount).map((entry, index) => {
1254 var scaled = scale.map(entry);
1255 if (!isWellBehavedNumber(scaled)) {
1256 return null;
1257 }
1258 return {
1259 coordinate: scaled + offset,
1260 value: entry,
1261 index,
1262 offset
1263 };
1264 }).filter(isNotNil);
1265 }
1266
1267 // When axis has duplicated text, serial numbers are used to generate scale
1268 return scale.domain().map((entry, index) => {
1269 var scaled = scale.map(entry);
1270 if (!isWellBehavedNumber(scaled)) {
1271 return null;
1272 }
1273 return {
1274 coordinate: scaled + offset,
1275 // @ts-expect-error can't use unknown as index
1276 value: duplicateDomain ? duplicateDomain[entry] : entry,
1277 index,
1278 offset
1279 };
1280 }).filter(isNotNil);
1281};
1282export var selectTicksOfGraphicalItem = createSelector([selectChartLayout, selectRenderableAxisSettings, selectAxisScale, selectAxisRange, selectDuplicateDomain, selectCategoricalDomain, pickAxisType], combineGraphicalItemTicks);
1283
1284/**
1285 * This is the internal representation of an axis along with its scale function.
1286 * Here we have already computed the scale function for the axis,
1287 * and replaced the union type of scale (string | function) with just the function type.
1288 */
1289
1290export var selectAxisWithScale = createSelector(selectBaseAxis, selectAxisScale, (axis, scale) => {
1291 if (axis == null || scale == null) {
1292 return undefined;
1293 }
1294 return _objectSpread(_objectSpread({}, axis), {}, {
1295 scale
1296 });
1297});
1298var selectZAxisScale = createSelector([selectBaseAxis, selectRealScaleType, selectAxisDomain, selectAxisRangeWithReverse], combineScaleFunction);
1299export var selectZAxisWithScale = createSelector((state, _axisType, axisId) => selectZAxisSettings(state, axisId), selectZAxisScale, (axis, scale) => {
1300 if (axis == null || scale == null) {
1301 return undefined;
1302 }
1303 return _objectSpread(_objectSpread({}, axis), {}, {
1304 scale
1305 });
1306});
1307
1308/**
1309 * We are also going to need to implement polar chart directions if we want to support keyboard controls for those.
1310 */
1311
1312export var selectChartDirection = createSelector([selectChartLayout, selectAllXAxes, selectAllYAxes], (layout, allXAxes, allYAxes) => {
1313 switch (layout) {
1314 case 'horizontal':
1315 {
1316 return allXAxes.some(axis => axis.reversed) ? 'right-to-left' : 'left-to-right';
1317 }
1318 case 'vertical':
1319 {
1320 return allYAxes.some(axis => axis.reversed) ? 'bottom-to-top' : 'top-to-bottom';
1321 }
1322 // TODO: make this better. For now, right arrow triggers "forward", left arrow "back"
1323 // however, the tooltip moves an unintuitive direction because of how the indices are rendered
1324 case 'centric':
1325 case 'radial':
1326 {
1327 return 'left-to-right';
1328 }
1329 default:
1330 {
1331 return undefined;
1332 }
1333 }
1334});
Note: See TracBrowser for help on using the repository browser.