@cdc/map 4.25.3 → 4.25.6

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.
Files changed (119) hide show
  1. package/.idea/map.iml +12 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/dist/cdcmap.js +31254 -32242
  5. package/examples/hex-colors.json +3 -3
  6. package/examples/m2.json +32904 -0
  7. package/examples/private/test.json +470 -1457
  8. package/examples/private/{mmr.json → wastewatermap.json} +86 -115
  9. package/index.html +36 -63
  10. package/package.json +7 -19
  11. package/src/CdcMap.tsx +56 -1552
  12. package/src/CdcMapComponent.tsx +608 -0
  13. package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +10 -0
  14. package/src/_stories/CdcMap.Legend.stories.tsx +67 -0
  15. package/src/_stories/CdcMap.Table.stories.tsx +19 -0
  16. package/src/_stories/CdcMap.stories.tsx +12 -1
  17. package/src/_stories/UsaMap.NoData.stories.tsx +4 -4
  18. package/src/_stories/_mock/default-patterns.json +8 -5
  19. package/src/_stories/_mock/legend-bins.json +428 -0
  20. package/{examples/private/default-patterns.json → src/_stories/_mock/legends/legend-tests.json} +36 -131
  21. package/src/cdcMapComponent.styles.css +9 -0
  22. package/src/components/Annotation/Annotation.Draggable.tsx +27 -26
  23. package/src/components/Annotation/AnnotationDropdown.tsx +5 -6
  24. package/src/components/BubbleList.tsx +135 -49
  25. package/src/components/CityList.tsx +89 -87
  26. package/src/components/DataTable.tsx +8 -8
  27. package/src/components/EditorPanel/components/EditorPanel.tsx +823 -885
  28. package/src/components/EditorPanel/components/Error.tsx +9 -2
  29. package/src/components/EditorPanel/components/HexShapeSettings.tsx +127 -141
  30. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +55 -86
  31. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +89 -75
  32. package/src/components/EditorPanel/components/editorPanel.styles.css +95 -0
  33. package/src/components/Geo.tsx +9 -1
  34. package/src/components/GoogleMap/components/GoogleMap.tsx +1 -1
  35. package/src/components/Legend/components/Legend.tsx +92 -87
  36. package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +128 -0
  37. package/src/components/Legend/components/LegendGroup/legend.group.css +27 -0
  38. package/src/components/Legend/components/LegendItem.Hex.tsx +4 -1
  39. package/src/components/Legend/components/index.scss +74 -17
  40. package/src/components/Modal.tsx +17 -7
  41. package/src/components/NavigationMenu.tsx +11 -9
  42. package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +12 -8
  43. package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +4 -4
  44. package/src/components/UsaMap/components/TerritoriesSection.tsx +33 -10
  45. package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +12 -10
  46. package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +12 -14
  47. package/src/components/UsaMap/components/Territory/TerritoryShape.ts +2 -1
  48. package/src/components/UsaMap/components/UsaMap.County.tsx +138 -96
  49. package/src/components/UsaMap/components/UsaMap.Region.styles.css +72 -0
  50. package/src/components/UsaMap/components/UsaMap.Region.tsx +56 -103
  51. package/src/components/UsaMap/components/UsaMap.SingleState.styles.css +10 -0
  52. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +65 -74
  53. package/src/components/UsaMap/components/UsaMap.State.tsx +112 -91
  54. package/src/components/UsaMap/helpers/map.ts +1 -1
  55. package/src/components/UsaMap/helpers/shapes.ts +20 -7
  56. package/src/components/WorldMap/WorldMap.tsx +64 -118
  57. package/src/components/WorldMap/worldMap.styles.css +28 -0
  58. package/src/components/ZoomControls.tsx +15 -13
  59. package/src/components/zoomControls.styles.css +53 -0
  60. package/src/context.ts +17 -9
  61. package/src/data/initial-state.js +5 -2
  62. package/src/helpers/addUIDs.ts +150 -0
  63. package/src/helpers/applyColorToLegend.ts +39 -64
  64. package/src/helpers/applyLegendToRow.ts +51 -0
  65. package/src/helpers/colorDistributions.ts +12 -0
  66. package/src/helpers/constants.ts +44 -0
  67. package/src/helpers/displayGeoName.ts +9 -2
  68. package/src/helpers/formatLegendLocation.ts +3 -2
  69. package/src/helpers/generateColorsArray.ts +2 -1
  70. package/src/helpers/generateRuntimeData.ts +78 -0
  71. package/src/helpers/generateRuntimeFilters.ts +63 -0
  72. package/src/helpers/generateRuntimeLegend.ts +566 -0
  73. package/src/helpers/generateRuntimeLegendHash.ts +16 -15
  74. package/src/helpers/getColumnNames.ts +19 -0
  75. package/src/helpers/getMapContainerClasses.ts +23 -0
  76. package/src/helpers/getStatePicked.ts +8 -0
  77. package/src/helpers/handleMapTabbing.ts +31 -0
  78. package/src/helpers/hashObj.ts +1 -1
  79. package/src/helpers/index.ts +22 -0
  80. package/src/helpers/navigationHandler.ts +3 -3
  81. package/src/helpers/resetLegendToggles.ts +13 -0
  82. package/src/helpers/setBinNumbers.ts +5 -0
  83. package/src/helpers/sortSpecialClassesLast.ts +7 -0
  84. package/src/helpers/tests/getColumnNames.test.ts +52 -0
  85. package/src/helpers/titleCase.ts +1 -1
  86. package/src/helpers/toggleLegendActive.ts +25 -0
  87. package/src/hooks/useApplyTooltipsToGeo.tsx +51 -0
  88. package/src/hooks/useColumnsRequiredChecker.ts +51 -0
  89. package/src/hooks/useGeoClickHandler.ts +45 -0
  90. package/src/hooks/useLegendSeparators.ts +26 -0
  91. package/src/hooks/useMapLayers.tsx +34 -60
  92. package/src/hooks/useModal.ts +22 -0
  93. package/src/hooks/useResizeObserver.ts +4 -5
  94. package/src/hooks/useStateZoom.tsx +52 -75
  95. package/src/hooks/useTooltip.ts +2 -3
  96. package/src/index.jsx +3 -9
  97. package/src/scss/editor-panel.scss +3 -99
  98. package/src/scss/main.scss +1 -19
  99. package/src/scss/map.scss +15 -220
  100. package/src/store/map.actions.ts +46 -0
  101. package/src/store/map.reducer.ts +96 -0
  102. package/src/types/Annotations.ts +24 -0
  103. package/src/types/MapConfig.ts +23 -3
  104. package/src/types/MapContext.ts +36 -35
  105. package/src/types/Modal.ts +1 -0
  106. package/src/types/RuntimeData.ts +3 -0
  107. package/examples/private/DEV-9644.json +0 -184
  108. package/examples/private/DEV-9989.json +0 -229
  109. package/examples/private/ardi.json +0 -180
  110. package/examples/private/colors 2.json +0 -416
  111. package/examples/private/colors.json +0 -416
  112. package/examples/private/colors.json.zip +0 -0
  113. package/examples/private/customColors.json +0 -45348
  114. package/examples/test.json +0 -183
  115. package/src/helpers/closeModal.ts +0 -9
  116. package/src/scss/btn.scss +0 -69
  117. package/src/scss/filters.scss +0 -27
  118. package/src/scss/variables.scss +0 -1
  119. /package/src/hooks/{useActiveElement.js → useActiveElement.ts} +0 -0
@@ -1,80 +1,55 @@
1
1
  import colorPalettes from '@cdc/core/data/colorPalettes'
2
2
  import chroma from 'chroma-js'
3
- import { type ChartConfig } from '@cdc/chart/src/types/ChartConfig'
4
- import isOlderVersion from '@cdc/core/helpers/isOlderVersion'
3
+ import { type MapConfig } from '@cdc/map/src/types/MapConfig'
4
+ import { colorDistributions } from './colorDistributions'
5
+
6
+ type LegendItem = {
7
+ special: boolean
8
+ }
5
9
 
6
10
  /**
7
11
  * applyColorToLegend
8
12
  * @param legendIdx legend item index
9
13
  * @param config chart config
10
14
  * @param result hash of legend items
11
- * @returns
15
+ * @returns string - the corresponding color for the legend item
12
16
  */
13
- export const applyColorToLegend = (legendIdx: number, config: ChartConfig, result = []) => {
14
- try {
15
- if (!config) throw new Error('Config is required')
16
-
17
- const colorDistributions = {
18
- 1: [1],
19
- 2: [1, 3],
20
- 3: [1, 3, 5],
21
- 4: [0, 2, 4, 6],
22
- 5: [0, 2, 4, 6, 7],
23
- 6: [0, 2, 3, 4, 5, 7],
24
- 7: [0, 2, 3, 4, 5, 6, 7],
25
- 8: [0, 2, 3, 4, 5, 6, 7, 8],
26
- 9: [0, 1, 2, 3, 4, 5, 6, 7, 8],
27
- 10: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
28
- }
29
-
30
- const specialClasses = config?.legend?.specialClasses
31
- const { general } = config || {}
32
- // Default to "bluegreen" color scheme if the passed color isn't valid
33
- let mapColorPalette = config.customColors || colorPalettes[config.color] || colorPalettes['bluegreen']
34
-
35
- // Handle Region Maps need for a 10th color
36
- if (general.geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
37
- if (!general.palette.isReversed) {
38
- mapColorPalette.push(chroma(mapColorPalette[8]).darken(0.75).hex())
39
- } else {
40
- mapColorPalette.unshift(chroma(mapColorPalette[0]).darken(0.75).hex())
41
- }
42
- }
43
-
44
- let colorIdx = legendIdx - specialClasses.length
17
+ export const applyColorToLegend = (legendIdx: number, config: MapConfig, result: LegendItem[] = []): string => {
18
+ if (!config) throw new Error('Config is required')
19
+
20
+ const { legend, customColors, general, color } = config
21
+ const { geoType, palette } = general
22
+ const specialClasses = legend?.specialClasses ?? []
23
+ const mapColorPalette = customColors ?? colorPalettes[color] ?? colorPalettes['bluegreen']
24
+
25
+ // Handle Region Maps need for a 10th color
26
+ if (geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
27
+ const newColor = chroma(mapColorPalette[palette.isReversed ? 0 : 8])
28
+ .darken(0.75)
29
+ .hex()
30
+ palette.isReversed ? mapColorPalette.unshift(newColor) : mapColorPalette.push(newColor)
31
+ }
45
32
 
46
- // Special Classes (No Data)
47
- if (result[legendIdx].special) {
48
- if (!config?.migrations?.addColorMigration) {
49
- const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses)
50
- return specialClassColors[legendIdx]
51
- } else {
52
- const specialClassColors = ['#A9AEB1', '#71767A']
53
- return specialClassColors[legendIdx]
54
- }
55
- }
33
+ const colorIdx = legendIdx - specialClasses.length
56
34
 
57
- if (config.color.includes('qualitative')) return mapColorPalette[colorIdx]
35
+ // Handle special classes coloring
36
+ if (result[legendIdx]?.special) {
37
+ const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses.length)
38
+ return specialClassColors[legendIdx]
39
+ }
58
40
 
59
- // If the current version is newer than 4.24.10, use the color palette
60
- if (!config?.migrations?.addColorMigration) {
61
- if (config.customColors) return mapColorPalette[legendIdx - specialClasses.length]
62
- }
41
+ // Use qualitative color palettes directly
42
+ if (color.includes('qualitative')) return mapColorPalette[colorIdx]
63
43
 
64
- let amt = Math.max(result.length - specialClasses.length, 1)
65
- let distributionArray = colorDistributions[amt]
66
- let specificColor
44
+ // Determine color distribution
45
+ const amt =
46
+ Math.max(result.length - specialClasses.length, 1) < 10
47
+ ? Math.max(result.length - specialClasses.length, 1)
48
+ : Object.keys(colorDistributions).length
49
+ const distributionArray = colorDistributions[amt] ?? []
67
50
 
68
- if (distributionArray) {
69
- specificColor = distributionArray[legendIdx - specialClasses.length]
70
- } else if (mapColorPalette[colorIdx]) {
71
- specificColor = colorIdx
72
- } else {
73
- specificColor = mapColorPalette.length - 1
74
- }
51
+ const specificColor =
52
+ distributionArray[legendIdx - specialClasses.length] ?? mapColorPalette[colorIdx] ?? mapColorPalette.at(-1)
75
53
 
76
- return mapColorPalette[specificColor]
77
- } catch (error) {
78
- console.error('Error in applyColorToLegend', error)
79
- }
54
+ return mapColorPalette[specificColor]
80
55
  }
@@ -0,0 +1,51 @@
1
+ import { generateColorsArray, hashObj } from '../helpers'
2
+ import colorPalettes from '@cdc/core/data/colorPalettes'
3
+ import { MapConfig } from '../types/MapConfig'
4
+ import { type RuntimeLegend } from '../types/runtimeLegend'
5
+
6
+ type Memo<T> = { current: Map<string, T> }
7
+
8
+ export const applyLegendToRow = (
9
+ rowObj: Record<string, any>,
10
+ config: MapConfig,
11
+ runtimeLegend: RuntimeLegend,
12
+ legendMemo: Memo<number>,
13
+ legendSpecialClassLastMemo: Memo<number>
14
+ ): string[] => {
15
+ if (!config) return null
16
+
17
+ const { general, color, legend } = config
18
+ const { type } = general
19
+ const { showSpecialClassesLast } = legend
20
+
21
+ try {
22
+ if (!rowObj) {
23
+ console.error('COVE: No rowObj in applyLegendToRow')
24
+ return null
25
+ }
26
+
27
+ if (type === 'navigation') {
28
+ const mapColorPalette = colorPalettes[color] ?? colorPalettes['bluegreenreverse']
29
+ return generateColorsArray(mapColorPalette[3])
30
+ }
31
+
32
+ const hash = hashObj(rowObj)
33
+
34
+ if (!legendMemo.current.has(hash)) {
35
+ return generateColorsArray()
36
+ }
37
+
38
+ const idx = legendMemo.current.get(hash)!
39
+ const disabledIdx = showSpecialClassesLast ? legendSpecialClassLastMemo.current.get(hash) ?? idx : idx
40
+
41
+ if (runtimeLegend.items?.[disabledIdx]?.disabled) {
42
+ return generateColorsArray()
43
+ }
44
+
45
+ const legendBinColor = runtimeLegend.items.find(o => o.bin === idx)?.color
46
+ return generateColorsArray(legendBinColor, runtimeLegend.items[idx]?.special)
47
+ } catch (e) {
48
+ console.error('COVE: ', e)
49
+ return null
50
+ }
51
+ }
@@ -0,0 +1,12 @@
1
+ export const colorDistributions = {
2
+ 1: [1],
3
+ 2: [1, 3],
4
+ 3: [1, 3, 5],
5
+ 4: [0, 2, 4, 6],
6
+ 5: [0, 2, 4, 6, 7],
7
+ 6: [0, 2, 3, 4, 5, 7],
8
+ 7: [0, 2, 3, 4, 5, 6, 7],
9
+ 8: [0, 2, 3, 4, 5, 6, 7, 8],
10
+ 9: [0, 1, 2, 3, 4, 5, 6, 7, 8],
11
+ 10: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
12
+ }
@@ -0,0 +1,44 @@
1
+ export const SVG_WIDTH = 880
2
+ export const SVG_HEIGHT = 500
3
+ export const SVG_PADDING = 50
4
+ export const SVG_VIEWBOX = `0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`
5
+ export const HEADER_COLORS = [
6
+ 'theme-blue',
7
+ 'theme-purple',
8
+ 'theme-brown',
9
+ 'theme-teal',
10
+ 'theme-pink',
11
+ 'theme-orange',
12
+ 'theme-slate',
13
+ 'theme-indigo',
14
+ 'theme-cyan',
15
+ 'theme-green',
16
+ 'theme-amber'
17
+ ]
18
+ export const MAX_ZOOM_LEVEL = 4
19
+
20
+ export const SUPPORTED_DC_NAMES = [
21
+ 'WASHINGTON D.C.',
22
+ 'DISTRICT OF COLUMBIA',
23
+ 'WASHINGTON DC',
24
+ 'DC',
25
+ 'WASHINGTON DC.',
26
+ 'D.C.',
27
+ 'D.C'
28
+ ] as const
29
+
30
+ export const GEO_TYPES = {
31
+ US: 'us',
32
+ US_REGION: 'us-region',
33
+ WORLD: 'world',
34
+ US_COUNTY: 'us-county',
35
+ SINGLE_STATE: 'single-state',
36
+ GOOGLE_MAP: 'google-map'
37
+ } as const
38
+
39
+ export const GEOCODE_TYPES = {
40
+ WORLD: 'world-geocode',
41
+ US: 'us-geocode'
42
+ } as const
43
+
44
+ export const DEFAULT_MAP_BACKGROUND = '#DFE1E2'
@@ -1,7 +1,14 @@
1
1
  import { titleCase } from './titleCase'
2
2
  import { supportedStates, supportedTerritories, supportedCountries, supportedCounties } from '../data/supported-geos'
3
3
 
4
- export const displayGeoName = (key, convertFipsCodes = true): string => {
4
+ /**
5
+ * Converts a geographic key to its display name.
6
+ *
7
+ * @param {string} key - The geographic key to convert.
8
+ * @param {boolean} [convertFipsCodes=true] - Whether to convert FIPS codes.
9
+ * @returns {string} - The display name for the geographic key.
10
+ */
11
+ export const displayGeoName = (key: string, convertFipsCodes = true): string => {
5
12
  if (!convertFipsCodes) return key
6
13
  const stateKeys = Object.keys(supportedStates)
7
14
  const territoryKeys = Object.keys(supportedTerritories)
@@ -41,7 +48,7 @@ export const displayGeoName = (key, convertFipsCodes = true): string => {
41
48
  value = dict[value]
42
49
  }
43
50
  // if you get here and it's 2 letters then DONT titleCase state abbreviations like "AL"
44
- if (value.length === 2 || value === 'U.S. Virgin Islands') {
51
+ if (value?.length === 2 || value === 'U.S. Virgin Islands') {
45
52
  return value
46
53
  } else {
47
54
  return titleCase(value)
@@ -1,6 +1,8 @@
1
1
  import { stateFipsToTwoDigit, supportedCounties } from '../data/supported-geos'
2
2
  import { titleCase } from './titleCase'
3
3
 
4
+ const countyKeySet = new Set(Object.keys(supportedCounties))
5
+
4
6
  export const formatLegendLocation = (key, runtimeLookup) => {
5
7
  let formattedName = ''
6
8
 
@@ -9,8 +11,7 @@ export const formatLegendLocation = (key, runtimeLookup) => {
9
11
  formattedName += stateName
10
12
  }
11
13
 
12
- const countyKeys = Object.keys(supportedCounties)
13
- if (countyKeys.includes(key)) {
14
+ if (countyKeySet.has(key)) {
14
15
  formattedName += ', ' + titleCase(supportedCounties[key])
15
16
  }
16
17
 
@@ -1,4 +1,5 @@
1
1
  import chroma from 'chroma-js'
2
+ import { DEFAULT_MAP_BACKGROUND } from './constants'
2
3
 
3
4
  /**
4
5
  * Generate an array of colors based on a given color [color, hoverColor, darkColor]
@@ -6,7 +7,7 @@ import chroma from 'chroma-js'
6
7
  * @param {boolean} special - A flag to determine if the hover color should be brighter or saturated
7
8
  * @returns {string[]} - An array of colors
8
9
  */
9
- export const generateColorsArray = (color: string = '#000000', special: boolean = false) => {
10
+ export const generateColorsArray = (color: string = DEFAULT_MAP_BACKGROUND, special: boolean = false) => {
10
11
  let colorObj = chroma(color)
11
12
  let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
12
13
  return [color, hoverColor, colorObj.darken(0.3).hex()]
@@ -0,0 +1,78 @@
1
+ import { addUIDs } from '.'
2
+ import numberFromString from '@cdc/core/helpers/numberFromString'
3
+ import { MapConfig } from '../types/MapConfig'
4
+ import { VizFilter } from '@cdc/core/types/VizFilter'
5
+ import { DataRow } from '../types/MapConfig'
6
+
7
+ const generateRuntimeData = (
8
+ configObj: MapConfig,
9
+ filters: VizFilter[],
10
+ hash: number,
11
+ isCategoryLegend: boolean,
12
+ keepNoUidRows = false
13
+ ): {
14
+ [uid: string]: DataRow
15
+ } => {
16
+ try {
17
+ const result: { [uid: string]: DataRow } = {}
18
+
19
+ // Adding property this way prevents it from being enumerated
20
+ Object.defineProperty(result, 'fromHash', {
21
+ value: hash
22
+ })
23
+
24
+ addUIDs(configObj, configObj.columns.geo.name)
25
+
26
+ configObj.data.forEach((row: DataRow) => {
27
+ if (!row.uid) {
28
+ if (!keepNoUidRows) return false // No UID for this row, we can't use for mapping
29
+ row.uid = row[configObj.columns.geo.name]
30
+ }
31
+ const configPrimaryName = configObj.columns.primary.name
32
+ const value = row[configPrimaryName]
33
+ const categoryLegend = typeof value === 'string' && isCategoryLegend
34
+ if (value && !categoryLegend) {
35
+ row[configPrimaryName] = numberFromString(value)
36
+ }
37
+
38
+ // If this is a navigation only map, skip if it doesn't have a URL
39
+
40
+ if ('navigation' === configObj.general.type) {
41
+ let navigateUrl = row[configObj.columns.navigate.name] || ''
42
+
43
+ if (undefined !== navigateUrl && typeof navigateUrl === 'string') {
44
+ // Strip hidden characters before we check length
45
+ navigateUrl = navigateUrl.replace(/(\r\n|\n|\r)/gm, '')
46
+ }
47
+ if (0 === navigateUrl?.length) {
48
+ return false
49
+ }
50
+ }
51
+
52
+ // Filters
53
+ if (filters?.length) {
54
+ for (let i = 0; i < filters.length; i++) {
55
+ const { columnName, active, type, filterStyle, subGrouping } = filters[i]
56
+ const isDataFilter = type !== 'url'
57
+ const matchingValue = String(active) === String(row[columnName]) // Group
58
+ if (isDataFilter && !matchingValue) return false // Bail out, data doesn't match the filter selection
59
+ if (filterStyle == 'nested-dropdown') {
60
+ const matchingSubValue = String(row[subGrouping?.columnName]) === String(subGrouping?.active)
61
+ if (subGrouping?.active && !matchingSubValue) {
62
+ return false // Bail out, data doesn't match the subgroup selection
63
+ }
64
+ }
65
+ }
66
+ }
67
+ // Don't add additional rows with same UID
68
+ if (result[row.uid] === undefined) {
69
+ result[row.uid] = row
70
+ }
71
+ })
72
+ return result
73
+ } catch (e) {
74
+ console.error('COVE: ', e) // eslint-disable-line
75
+ }
76
+ }
77
+
78
+ export default generateRuntimeData
@@ -0,0 +1,63 @@
1
+ import { getUniqueValues } from './index'
2
+ import { handleSorting } from '@cdc/core/components/Filters'
3
+
4
+ export const generateRuntimeFilters = (state, hash, runtimeFilters) => {
5
+ if (typeof state === 'undefined' || undefined === state.filters || state.filters.length === 0) return []
6
+
7
+ const filters = state?.filters.map(
8
+ (
9
+ {
10
+ columnName,
11
+ label,
12
+ labels,
13
+ queryParameter,
14
+ orderedValues,
15
+ active,
16
+ values,
17
+ type,
18
+ showDropdown,
19
+ setByQueryParameter,
20
+ order
21
+ },
22
+ idx
23
+ ) => {
24
+ const newFilter = runtimeFilters[idx] || {}
25
+
26
+ const sort = (a, b) => {
27
+ const asc = order !== 'desc'
28
+ return String(asc ? a : b).localeCompare(String(asc ? b : a), 'en', { numeric: true })
29
+ }
30
+
31
+ if (type !== 'url') {
32
+ values = getUniqueValues(state.data, columnName)
33
+
34
+ if (state.filters[idx].order === 'cust') {
35
+ if (state.filters[idx]?.values.length > 0) {
36
+ values = state.filters[idx].values
37
+ }
38
+ } else {
39
+ values = values.sort(sort)
40
+ }
41
+ }
42
+
43
+ newFilter.order = state.filters[idx].order ? state.filters[idx].order : 'asc'
44
+ newFilter.type = type
45
+ newFilter.label = label ?? ''
46
+ newFilter.columnName = columnName
47
+ newFilter.orderedValues = orderedValues
48
+ newFilter.queryParameter = queryParameter
49
+ newFilter.labels = labels
50
+ newFilter.values = values
51
+ newFilter.setByQueryParameter = setByQueryParameter
52
+ handleSorting(newFilter)
53
+ newFilter.active = active ?? values[0] // Default to first found value
54
+ newFilter.filterStyle = state.filters[idx].filterStyle ? state.filters[idx].filterStyle : 'dropdown'
55
+ newFilter.showDropdown = showDropdown
56
+ newFilter.subGrouping = state.filters[idx].subGrouping
57
+
58
+ return newFilter
59
+ }
60
+ )
61
+ if (hash) filters.fromHash = hash
62
+ return filters
63
+ }