@cdc/map 4.25.3 → 4.25.5-1

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 (111) hide show
  1. package/dist/cdcmap.js +38945 -41511
  2. package/examples/hex-colors.json +3 -3
  3. package/examples/private/test.json +470 -1457
  4. package/examples/private/{mmr.json → wastewatermap.json} +86 -115
  5. package/index.html +13 -41
  6. package/package.json +4 -10
  7. package/src/CdcMap.tsx +51 -1555
  8. package/src/CdcMapComponent.tsx +594 -0
  9. package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +10 -0
  10. package/src/_stories/CdcMap.Legend.stories.tsx +67 -0
  11. package/src/_stories/CdcMap.stories.tsx +4 -1
  12. package/src/_stories/UsaMap.NoData.stories.tsx +4 -4
  13. package/{examples/private/default-patterns.json → src/_stories/_mock/legends/legend-tests.json} +36 -131
  14. package/src/cdcMapComponent.styles.css +9 -0
  15. package/src/components/Annotation/Annotation.Draggable.tsx +27 -26
  16. package/src/components/Annotation/AnnotationDropdown.tsx +5 -6
  17. package/src/components/BubbleList.tsx +135 -49
  18. package/src/components/CityList.tsx +89 -87
  19. package/src/components/DataTable.tsx +8 -8
  20. package/src/components/EditorPanel/components/EditorPanel.tsx +714 -820
  21. package/src/components/EditorPanel/components/Error.tsx +9 -2
  22. package/src/components/EditorPanel/components/HexShapeSettings.tsx +127 -141
  23. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +55 -86
  24. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +89 -75
  25. package/src/components/EditorPanel/components/editorPanel.styles.css +95 -0
  26. package/src/components/Geo.tsx +9 -1
  27. package/src/components/GoogleMap/components/GoogleMap.tsx +1 -1
  28. package/src/components/Legend/components/Legend.tsx +92 -87
  29. package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +128 -0
  30. package/src/components/Legend/components/LegendGroup/legend.group.css +27 -0
  31. package/src/components/Legend/components/LegendItem.Hex.tsx +4 -1
  32. package/src/components/Legend/components/index.scss +18 -6
  33. package/src/components/Modal.tsx +17 -7
  34. package/src/components/NavigationMenu.tsx +11 -9
  35. package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +12 -8
  36. package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +4 -4
  37. package/src/components/UsaMap/components/TerritoriesSection.tsx +33 -10
  38. package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +12 -10
  39. package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +12 -14
  40. package/src/components/UsaMap/components/Territory/TerritoryShape.ts +2 -1
  41. package/src/components/UsaMap/components/UsaMap.County.tsx +138 -96
  42. package/src/components/UsaMap/components/UsaMap.Region.styles.css +72 -0
  43. package/src/components/UsaMap/components/UsaMap.Region.tsx +56 -103
  44. package/src/components/UsaMap/components/UsaMap.SingleState.styles.css +10 -0
  45. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +59 -66
  46. package/src/components/UsaMap/components/UsaMap.State.tsx +112 -91
  47. package/src/components/UsaMap/helpers/map.ts +1 -1
  48. package/src/components/UsaMap/helpers/shapes.ts +20 -7
  49. package/src/components/WorldMap/WorldMap.tsx +64 -118
  50. package/src/components/WorldMap/worldMap.styles.css +28 -0
  51. package/src/components/ZoomControls.tsx +15 -13
  52. package/src/components/zoomControls.styles.css +53 -0
  53. package/src/context.ts +17 -9
  54. package/src/data/initial-state.js +5 -2
  55. package/src/helpers/addUIDs.ts +151 -0
  56. package/src/helpers/applyColorToLegend.ts +39 -64
  57. package/src/helpers/applyLegendToRow.ts +51 -0
  58. package/src/helpers/colorDistributions.ts +12 -0
  59. package/src/helpers/constants.ts +44 -0
  60. package/src/helpers/displayGeoName.ts +9 -2
  61. package/src/helpers/generateColorsArray.ts +2 -1
  62. package/src/helpers/generateRuntimeData.ts +74 -0
  63. package/src/helpers/generateRuntimeFilters.ts +63 -0
  64. package/src/helpers/generateRuntimeLegend.ts +537 -0
  65. package/src/helpers/generateRuntimeLegendHash.ts +16 -15
  66. package/src/helpers/getColumnNames.ts +19 -0
  67. package/src/helpers/getMapContainerClasses.ts +23 -0
  68. package/src/helpers/handleMapTabbing.ts +31 -0
  69. package/src/helpers/hashObj.ts +1 -1
  70. package/src/helpers/index.ts +22 -0
  71. package/src/helpers/navigationHandler.ts +3 -3
  72. package/src/helpers/resetLegendToggles.ts +13 -0
  73. package/src/helpers/setBinNumbers.ts +5 -0
  74. package/src/helpers/sortSpecialClassesLast.ts +7 -0
  75. package/src/helpers/tests/getColumnNames.test.ts +52 -0
  76. package/src/helpers/titleCase.ts +1 -1
  77. package/src/helpers/toggleLegendActive.ts +25 -0
  78. package/src/hooks/useApplyTooltipsToGeo.tsx +51 -0
  79. package/src/hooks/useColumnsRequiredChecker.ts +51 -0
  80. package/src/hooks/useGeoClickHandler.ts +45 -0
  81. package/src/hooks/useLegendSeparators.ts +26 -0
  82. package/src/hooks/useMapLayers.tsx +34 -60
  83. package/src/hooks/useModal.ts +22 -0
  84. package/src/hooks/useResizeObserver.ts +4 -5
  85. package/src/hooks/useStateZoom.tsx +52 -75
  86. package/src/hooks/useTooltip.ts +2 -3
  87. package/src/index.jsx +3 -9
  88. package/src/scss/editor-panel.scss +3 -99
  89. package/src/scss/main.scss +1 -19
  90. package/src/scss/map.scss +15 -220
  91. package/src/store/map.actions.ts +46 -0
  92. package/src/store/map.reducer.ts +96 -0
  93. package/src/types/Annotations.ts +24 -0
  94. package/src/types/MapConfig.ts +23 -3
  95. package/src/types/MapContext.ts +36 -35
  96. package/src/types/Modal.ts +1 -0
  97. package/src/types/RuntimeData.ts +3 -0
  98. package/LICENSE +0 -201
  99. package/examples/private/DEV-9644.json +0 -184
  100. package/examples/private/DEV-9989.json +0 -229
  101. package/examples/private/ardi.json +0 -180
  102. package/examples/private/colors 2.json +0 -416
  103. package/examples/private/colors.json +0 -416
  104. package/examples/private/colors.json.zip +0 -0
  105. package/examples/private/customColors.json +0 -45348
  106. package/examples/test.json +0 -183
  107. package/src/helpers/closeModal.ts +0 -9
  108. package/src/scss/btn.scss +0 -69
  109. package/src/scss/filters.scss +0 -27
  110. package/src/scss/variables.scss +0 -1
  111. /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,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,74 @@
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
+ ): {
13
+ [uid: string]: DataRow
14
+ } => {
15
+ try {
16
+ const result: { [uid: string]: DataRow } = {}
17
+
18
+ // Adding property this way prevents it from being enumerated
19
+ Object.defineProperty(result, 'fromHash', {
20
+ value: hash
21
+ })
22
+
23
+ addUIDs(configObj, configObj.columns.geo.name)
24
+
25
+ configObj.data.forEach((row: DataRow) => {
26
+ if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
27
+ const configPrimaryName = configObj.columns.primary.name
28
+ const value = row[configPrimaryName]
29
+ const categoryLegend = typeof value === 'string' && isCategoryLegend
30
+ if (value && !categoryLegend) {
31
+ row[configPrimaryName] = numberFromString(value)
32
+ }
33
+
34
+ // If this is a navigation only map, skip if it doesn't have a URL
35
+
36
+ if ('navigation' === configObj.general.type) {
37
+ let navigateUrl = row[configObj.columns.navigate.name] || ''
38
+
39
+ if (undefined !== navigateUrl && typeof navigateUrl === 'string') {
40
+ // Strip hidden characters before we check length
41
+ navigateUrl = navigateUrl.replace(/(\r\n|\n|\r)/gm, '')
42
+ }
43
+ if (0 === navigateUrl?.length) {
44
+ return false
45
+ }
46
+ }
47
+
48
+ // Filters
49
+ if (filters?.length) {
50
+ for (let i = 0; i < filters.length; i++) {
51
+ const { columnName, active, type, filterStyle, subGrouping } = filters[i]
52
+ const isDataFilter = type !== 'url'
53
+ const matchingValue = String(active) === String(row[columnName]) // Group
54
+ if (isDataFilter && !matchingValue) return false // Bail out, data doesn't match the filter selection
55
+ if (filterStyle == 'nested-dropdown') {
56
+ const matchingSubValue = String(row[subGrouping?.columnName]) === String(subGrouping?.active)
57
+ if (subGrouping?.active && !matchingSubValue) {
58
+ return false // Bail out, data doesn't match the subgroup selection
59
+ }
60
+ }
61
+ }
62
+ }
63
+ // Don't add additional rows with same UID
64
+ if (result[row.uid] === undefined) {
65
+ result[row.uid] = row
66
+ }
67
+ })
68
+ return result
69
+ } catch (e) {
70
+ console.error('COVE: ', e) // eslint-disable-line
71
+ }
72
+ }
73
+
74
+ 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
+ }