@splunk/visualizations 27.1.0 → 27.2.0

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 (52) hide show
  1. package/Area.js +2 -2
  2. package/Bar.js +2 -2
  3. package/Bubble.js +2 -2
  4. package/ChoroplethSvg.js +6 -9
  5. package/ChoroplethSvg.js.map +3 -3
  6. package/Column.js +2 -2
  7. package/Ellipse.js +2 -2
  8. package/Events.js +106 -491
  9. package/Events.js.map +4 -4
  10. package/FillerGauge.js +3 -3
  11. package/FillerGauge.js.map +3 -3
  12. package/Image.js +2 -2
  13. package/Line.js +2 -2
  14. package/LinkGraph.js +23 -18
  15. package/LinkGraph.js.map +2 -2
  16. package/Map.config.js +114 -72
  17. package/Map.config.js.map +4 -4
  18. package/Map.js +139 -86
  19. package/Map.js.map +4 -4
  20. package/Markdown.js +2 -2
  21. package/MarkerGauge.js +2 -2
  22. package/ParallelCoordinates.js +3 -3
  23. package/ParallelCoordinates.js.map +3 -3
  24. package/Pie.js +2 -2
  25. package/Punchcard.js +199 -26
  26. package/Punchcard.js.map +4 -4
  27. package/Rectangle.js +2 -2
  28. package/Sankey.js +2 -2
  29. package/Scatter.js +2 -2
  30. package/SingleValue.js +19 -9
  31. package/SingleValue.js.map +3 -3
  32. package/SingleValueBasic.js +1 -1
  33. package/SingleValueBasic.js.map +3 -3
  34. package/SingleValueIcon.js +380 -117
  35. package/SingleValueIcon.js.map +4 -4
  36. package/SingleValueRadial.js +16 -9
  37. package/SingleValueRadial.js.map +3 -3
  38. package/SparkLine.js +1 -1
  39. package/SparkLine.js.map +3 -3
  40. package/Table.js +15 -10
  41. package/Table.js.map +3 -3
  42. package/Timeline.config.js +418 -0
  43. package/Timeline.config.js.map +7 -0
  44. package/Timeline.js +3074 -0
  45. package/Timeline.js.map +7 -0
  46. package/common/OptionsDoc.js +2 -2
  47. package/common/OptionsDoc.js.map +1 -1
  48. package/common/utils/mapUtils.js.map +2 -2
  49. package/common/utils/singleValueUtils.js +18 -8
  50. package/common/utils/singleValueUtils.js.map +2 -2
  51. package/common/withDashboardViz.js +2 -2
  52. package/package.json +43 -31
@@ -197,7 +197,7 @@ var PairTitle = styled_components_default.span`
197
197
  width: 80px;
198
198
  `;
199
199
  var PairValue = styled_components_default.span`
200
- font-family: 'Splunk Platform Mono', 'monospace';
200
+ font-family: 'Splunk Platform Mono', monospace;
201
201
  white-space: pre;
202
202
  `;
203
203
  var PairValueJSON = styled_components_default.div`
@@ -207,7 +207,7 @@ var PairValueJSON = styled_components_default.div`
207
207
  }
208
208
  code {
209
209
  font-size: 12px;
210
- font-family: 'Splunk Platform Mono', 'monospace';
210
+ font-family: 'Splunk Platform Mono', monospace;
211
211
  }
212
212
  `;
213
213
  var PropertiesWrapper = styled_components_default.div`
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/common/OptionsDoc.jsx", "esm-externals:react", "esm-externals:prop-types", "esm-externals:lodash/isEmpty", "esm-externals:@splunk/ui-utils/i18n", "esm-externals:@splunk/react-ui/Heading", "esm-externals:@splunk/react-ui/Markdown", "esm-externals:styled-components", "esm-externals:lodash", "esm-externals:@splunk/visualizations-shared/configUtils", "../.storybook/utils/storybookUtils.ts"],
4
- "sourcesContent": ["import React from 'react';\nimport T from 'prop-types';\nimport isEmpty from 'lodash/isEmpty';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport Heading from '@splunk/react-ui/Heading';\nimport Markdown from '@splunk/react-ui/Markdown';\nimport styled from 'styled-components';\nimport { merge } from 'lodash';\nimport { getOptionDisplayType, getPatternOptions } from '../../.storybook/utils/storybookUtils';\n\nconst Option = styled.div`\n margin-top: 20px;\n`;\nconst OptionName = styled.div`\n color: #5ca300;\n padding-bottom: 5px;\n`;\nconst PairContainer = styled.div`\n margin-left: 40px;\n margin-top: 10px;\n`;\nconst PairTitle = styled.span`\n display: inline-block;\n color: #8293a7;\n width: 80px;\n`;\n\nconst PairValue = styled.span`\n font-family: 'Splunk Platform Mono', 'monospace';\n white-space: pre;\n`;\n\nconst PairValueJSON = styled.div`\n margin-left: 80px;\n pre {\n margin: 0;\n }\n code {\n font-size: 12px;\n font-family: 'Splunk Platform Mono', 'monospace';\n }\n`;\n\nconst PropertiesWrapper = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 0 : 40)}px;\n margin-top: 20px;\n`;\n\nconst PropertiesContainer = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 40 : 0)}px;\n margin-top: 10px;\n`;\n\nconst PropertiesContent = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 40 : 0)}px;\n`;\n\n/**\n * @method isOneOfJsonSchema\n * @param {object} item\n * @returns {boolean}\n */\nconst isOneOfJsonSchema = item => item.oneOf && Array.isArray(item.oneOf);\n\n/**\n * get Or type as string\n * @method getOrType\n * @param {object} item\n * @param {string} res\n * @returns {string} res eg: (string | number)\n */\nconst getOrType = item => {\n let res = '';\n\n if (isOneOfJsonSchema(item)) {\n res = item.oneOf\n .map(one => {\n if (one.type !== 'array') {\n return one.type;\n }\n // eslint-disable-next-line no-use-before-define\n return getArrayType(one, '');\n })\n .join(' | ');\n } else if (Array.isArray(item.type)) {\n if (isEmpty(item.default)) {\n return item.type.join(' | ');\n }\n\n res = item.type.filter(itemType => itemType !== 'string').join(' | ');\n res += ' | ';\n res += `\"${item.default}\"`;\n }\n\n return res;\n};\n\n/**\n * get the array type as string\n * @method getArrayType\n * @param {object} item\n * @param {string} res\n * @returns {string} res eg: arrayOf(arrayOf(string | number | arrayOf(string | number)))\n */\nconst getArrayType = (item, res = '') => {\n if (item.type !== 'array') {\n if (Array.isArray(item.type) || isOneOfJsonSchema(item)) {\n return getOrType(item);\n }\n\n return item.type;\n }\n\n if (item.type === 'array') {\n res += 'arrayOf('; // eslint-disable-line no-param-reassign\n }\n res += getArrayType(item.items, ''); // eslint-disable-line no-param-reassign\n res += ')'; // eslint-disable-line no-param-reassign\n return res;\n};\n\n/**\n * get the type of this option item\n * @method getType\n * @param {ojbect} item option item\n * @returns {string} type\n */\nexport const getType = item => {\n if (isOneOfJsonSchema(item)) {\n return `oneOf(${getOrType(item)})`;\n }\n if (item.enum && Array.isArray(item.enum)) {\n const values =\n !isEmpty(item.enum) && typeof item.enum[0] === 'string'\n ? item.enum.map(v => `\"${v}\"`).join(', ')\n : item.enum.join(', ');\n\n return `oneOf([${values}])`;\n }\n\n if (Array.isArray(item.type)) {\n return getOrType(item);\n }\n\n if (item.type === 'array') {\n if ('items' in item) {\n return `arrayOf(${getType(item.items)})`;\n }\n return 'array';\n }\n return item.type;\n};\n\n/**\n * get the default value as string\n * @method getDefaultValue\n * @param {object | boolean | number | string} defaultValue\n * @returns {string | object[]} default value\n */\nconst getDefaultValue = defaultValue => {\n if (typeof defaultValue === 'boolean' || typeof defaultValue === 'number') {\n return defaultValue.toString();\n }\n if (Array.isArray(defaultValue)) {\n if (defaultValue.length > 1 && typeof defaultValue[0] === 'object') {\n // return the array only if the defaultValue is an object array\n return defaultValue;\n }\n const values = defaultValue.map(v => JSON.stringify(v)).join(', ');\n return `[${values}]`;\n }\n return defaultValue;\n};\n\nconst Pair = ({ title, content }) => (\n <PairContainer>\n <PairTitle>{`${title}:`}</PairTitle>\n {Array.isArray(content) ? (\n <PairValueJSON>\n <pre>\n <code>{JSON.stringify(content, null, 2)}</code>\n </pre>\n </PairValueJSON>\n ) : (\n <PairValue>{content}</PairValue>\n )}\n </PairContainer>\n);\n\nPair.propTypes = {\n title: T.string,\n content: T.oneOfType([T.string, T.arrayOf(T.object)]),\n};\n\nconst PropertyItems = ({ isPatternProperty = false, propsItems }) => (\n <PropertiesContainer isPatternProperty={isPatternProperty}>\n {isPatternProperty ? <PairTitle>{_('[fieldName]:')}</PairTitle> : null}\n <PropertiesContent isPatternProperty={isPatternProperty}>{propsItems}</PropertiesContent>\n </PropertiesContainer>\n);\n\nPropertyItems.propTypes = {\n isPatternProperty: T.bool,\n propsItems: T.array,\n};\n\nconst OptionItem = ({ name, type, desc, defaultValue, enumerable, PropertiesSection }) => (\n <Option>\n <OptionName>{name}</OptionName>\n {desc ? <Markdown style={{ marginLeft: 40 }} text={desc} /> : null}\n <Pair title={_('Type')} content={type} />\n {enumerable?.length > 0 && (\n <Pair\n title={_('oneOf')}\n content={`(${enumerable\n .map(\n entry =>\n `${typeof entry === 'string' ? '\"' : ''}${entry}${\n typeof entry === 'string' ? '\"' : ''\n }`\n )\n .join(' | ')})`}\n />\n )}\n {defaultValue && <Pair title={_('Default')} content={defaultValue} />}\n {PropertiesSection}\n </Option>\n);\n\nOptionItem.propTypes = {\n name: T.string,\n type: T.string,\n desc: T.string,\n enumerable: T.arrayOf(T.oneOfType([T.string, T.number])),\n defaultValue: T.oneOfType([T.string, T.arrayOf(T.object)]),\n PropertiesSection: T.element,\n};\n\nOptionItem.default = {\n PropertiesItem: null,\n};\n\nconst getPropertiesSection = (properties, patternProperties) => {\n let allProperties = [];\n let isPatternProperty = false;\n\n // the properties either comes from property field of the option schema item\n // or from the property field of each patternProperties of the option schema item\n // can check table tableFormat and columnFormat as examples\n if (!isEmpty(properties)) {\n allProperties = [properties];\n } else if (!isEmpty(patternProperties)) {\n Object.keys(patternProperties).forEach(patternKey => {\n const propsInPattern = patternProperties[patternKey].properties;\n if (propsInPattern) {\n allProperties.push(propsInPattern);\n }\n });\n\n isPatternProperty = true;\n }\n\n if (allProperties.length) {\n const allPropsItems = allProperties.map(props => {\n const propsItems = Object.keys(props).map(pKey => {\n const p = props[pKey];\n let pType = p.anyOf?.[0]\n ? getOptionDisplayType({ ...p.anyOf?.[0], enum: p.enum })\n : getOptionDisplayType({ ...p, enum: p.enum });\n const pDefault = getDefaultValue(p.default);\n\n let pEnumerable;\n // get nested oneOf property listing\n if (typeof p.anyOf?.[0]?.pattern === 'string') {\n pEnumerable = getPatternOptions(p.anyOf[0].pattern);\n } else if (p.anyOf?.[0]?.items?.enum?.length > 0) {\n // quick fix for nested `columnFormat` enumerables that replaces enums within brackets with raw JS types\n pType = pType.replace(/\\((.+?)\\)/g, 'string');\n pEnumerable = p.anyOf[0].items.enum;\n } else if (p.anyOf?.[0]?.items?.items?.enum?.length > 0) {\n // quick fix for nested `tableFormat` enumerables that replaces enums within brackets with raw JS types\n pType = pType.replace(/\\((.+?)\\)/g, 'string');\n pEnumerable = p.anyOf[0].items.items.enum;\n } else if (p.enum) {\n pEnumerable = p.enum;\n }\n\n // use the JS types (e.g. string, number) of the nested property if the nested property is an enumerable\n if (pEnumerable?.length) {\n pType = p.anyOf?.[0]?.type !== 'array' ? p.anyOf?.[0]?.type : pType;\n if (Array.isArray(pType)) {\n pType = pType.join(' | ');\n }\n }\n\n return (\n <OptionItem\n key={pKey}\n name={pKey}\n type={pType}\n enumerable={pEnumerable}\n desc={p.description}\n defaultValue={pDefault}\n />\n );\n });\n return (\n <PropertyItems\n key={propsItems}\n isPatternProperty={isPatternProperty}\n propsItems={propsItems}\n />\n );\n });\n\n return <PropertiesWrapper isPatternProperty={isPatternProperty}>{allPropsItems}</PropertiesWrapper>;\n }\n return null;\n};\n\nconst OptionsDoc = ({ options, description }) => (\n <div>\n {options.length === 0 ? (\n <Heading level={4}> No Options</Heading>\n ) : (\n <Heading level={4}>Options</Heading>\n )}\n {description && <div>{description}</div>}\n {Object.entries(options).map(([key, item]) => {\n let type;\n let enumerable = [];\n let PropertiesSection = null;\n\n // get oneOf property listing\n if (typeof item.anyOf?.[0]?.pattern === 'string') {\n enumerable = getPatternOptions(item.anyOf[0].pattern);\n } else if (item.anyOf?.[0]?.enum) {\n enumerable = item.anyOf?.[0]?.enum;\n } else if (item.enum) {\n enumerable = item.enum;\n }\n\n // get the nested options inside {option}.items.anyof. e.g. 'layers' in Map\n if (item.anyOf?.[0]?.type === 'array' && 'anyOf' in item.anyOf?.[0]?.items) {\n type = getOptionDisplayType(item);\n const { patternProperties } = item;\n // merge the 3 objects together instead of showing the longest options in the array\n const option = item.anyOf?.[0]?.items?.anyOf;\n const mergedOptions = option.reduce((prev, next) => merge(prev, next), {});\n const { properties } = mergedOptions;\n PropertiesSection = getPropertiesSection(properties, patternProperties);\n return (\n <OptionItem\n key={key}\n name={key}\n type={type}\n enumerable={enumerable}\n desc={item.description}\n PropertiesSection={PropertiesSection}\n />\n );\n }\n\n if (item.type === 'object') {\n // get properties for object type\n type = item.type;\n const { properties } = item;\n const { patternProperties } = item;\n PropertiesSection = getPropertiesSection(properties, patternProperties);\n } else if (enumerable?.length) {\n // use the JS types (e.g. string, number) of the property if the property is an enumerable\n type = item.anyOf?.[0]?.type;\n if (Array.isArray(type)) {\n type = type.join(' | ');\n }\n } else {\n type = getOptionDisplayType({ ...item.anyOf[0], enum: item.enum });\n }\n\n return (\n <OptionItem\n key={key}\n name={key}\n // item.anyOf in the config.ts is a tuple which holds [{ type, pattern, items }, { type, pattern: DYNAMIC_OPTIONS_PATTERN }]\n type={type}\n enumerable={enumerable}\n desc={item.description}\n defaultValue={getDefaultValue(item.default)}\n PropertiesSection={PropertiesSection}\n />\n );\n })}\n </div>\n);\n\nOptionsDoc.propTypes = {\n options: T.object.isRequired,\n description: T.string,\n};\n\nexport default OptionsDoc;\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"prop-types\";\nexport * from \"prop-types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash/isEmpty\";\nexport * from \"lodash/isEmpty\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Heading\";\nexport * from \"@splunk/react-ui/Heading\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Markdown\";\nexport * from \"@splunk/react-ui/Markdown\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/configUtils\";\nexport * from \"@splunk/visualizations-shared/configUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { get, omit, reduce, toNumber, isString } from 'lodash';\nimport type { OptionsSchema } from '@splunk/visualization-schemas';\nimport { isDynamicOption } from '@splunk/visualizations-shared/configUtils';\n\ninterface ArgTypeControl {\n type: string;\n options?: string[];\n min?: number;\n max?: number;\n}\n\nexport interface ArgTypeEntry {\n description?: string;\n control: ArgTypeControl;\n name: string;\n defaultValue?: any;\n type: { required: boolean };\n optionType: string;\n table: {\n type: { summary: string };\n defaultValue?: { summary: any };\n category?: string;\n subcategory?: string;\n disable?: boolean;\n };\n}\n\nexport interface ArgTypes {\n [key: string]: ArgTypeEntry;\n}\n\ntype StoriesList = RegExp | string[];\n\n/**\n * Returns type options from pattern\n * @example\n * // returns ['fixed', 'absolute', 'off']\n * getPatternOptions('\\$(\\w+:)?([^$|:]+?)(\\|[|\\w]+)?\\$|^fixed$|^absolute$|^off$')\n * @example\n * // returns []\n * getPatternOptions('^>.*')\n * @param {string} patternString - visualization option type pattern\n * @return {string[]} array of type options\n */\nexport const getPatternOptions = (patternString): string[] => {\n if (patternString.indexOf('^#[') === 0) {\n return patternString.slice(1).replace(/\\$/g, '').split('|^');\n }\n return patternString.replace(/\\$/g, '').split('|^').slice(1);\n};\n/**\n * Returns Storybook display type for an option\n * @param {object} option - visualization option\n * @return {string} Storybook display type\n */\nexport const getOptionDisplayType = (option): string => {\n const { oneOf, anyOf, type, enum: en, pattern, items } = option;\n let displayTypes: string[] = [];\n\n // wrap values in quotes only if enum or pattern is string\n const conditionalQuote = type === 'string' ? '\"' : '';\n if (en && Array.isArray(en)) {\n displayTypes = en.map(e => {\n const enumQuote = typeof e === 'string' ? '\"' : '';\n return `${enumQuote}${e}${enumQuote}`;\n });\n } else if (type === 'array' && items) {\n return `${getOptionDisplayType(items)}[]`;\n } else if (anyOf && Array.isArray(anyOf)) {\n return getOptionDisplayType(anyOf[0]);\n } else if (oneOf && Array.isArray(oneOf)) {\n displayTypes = oneOf.map(item => getOptionDisplayType(item));\n } else if (Array.isArray(type)) {\n displayTypes = type;\n } else if (pattern) {\n displayTypes = getPatternOptions(pattern).map(p => `${conditionalQuote}${p}${conditionalQuote}`);\n }\n\n if (displayTypes.length > 0) {\n return `(${displayTypes.join(' | ')})`;\n }\n return type;\n};\n\n/**\n * Returns Storybook control type for an option\n * @param {object} option - visualization option\n * @param {string} optionKey - visualization option key\n * @return {ArgTypeControl} Storybook control object\n */\nexport const getOptionControl = (option, optionKey): ArgTypeControl => {\n const { anyOf } = option;\n const schema = Array.isArray(anyOf) && anyOf.length ? anyOf[0] : option;\n\n const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n const { maximum, minimum, enum: en } = schema;\n\n const isColorOption = new RegExp(/color/, 'i').test(optionKey) && type !== 'array';\n\n if (isColorOption) {\n return { type: 'color' };\n } else if (en && Array.isArray(en)) {\n return { type: 'select', options: en };\n } else if (anyOf && type === 'string' && anyOf[0].pattern) {\n return { type: 'select', options: getPatternOptions(anyOf[0].pattern) };\n } else if (type === 'number' && (minimum || maximum)) {\n return {\n type: 'range',\n ...(typeof minimum === 'number' && { min: minimum }),\n ...(typeof maximum === 'number' && { max: maximum }),\n };\n } else if (type === 'string') {\n return { type: 'text' };\n }\n\n return { type };\n};\n\n/**\n * platform specific visualization option argTypes\n */\nconst objectTableControl = { control: { type: 'object' } };\nconst disableTableControl = { table: { disable: true } };\nexport const platformOptionArgTypes = {\n context: objectTableControl,\n dataSources: objectTableControl,\n dataSource: disableTableControl,\n options: disableTableControl,\n onEventTrigger: { action: 'eventTrigger', ...disableTableControl },\n hasEventHandlers: disableTableControl,\n};\n\n/**\n * Returns formatted Storybook argTypes for a visualization from its options schema\n * @param {OptionsSchema} options - visualization options\n * @param {string[]} requiredProps - required visualization props\n * @param {boolean} isPlatformViz - indicates if pure or platform visualization\n * @param {string} subcategory - nested property parent option name\n * @return {ArgTypes} Storybook argTypes\n */\nexport const optionsSchemaToArgTypes = ({\n options = {},\n requiredProps = [],\n isPlatformViz = false,\n subcategory = null,\n}: {\n options: OptionsSchema;\n requiredProps: string[];\n isPlatformViz?: boolean;\n subcategory?: string;\n}): ArgTypes => {\n const validObjectTypeOptions = [\n 'lineDashStylesByField',\n 'seriesColorsByField',\n 'fieldActions',\n 'highlightValuesByField',\n ];\n let argTypes: ArgTypes = {};\n Object.keys(options).forEach(optionKey => {\n const option = get(options, optionKey);\n if (option.type === 'object' && !validObjectTypeOptions.includes(optionKey)) {\n // do not support controls for patternProperties, only nested properties\n if (option.properties) {\n argTypes = {\n ...argTypes,\n ...optionsSchemaToArgTypes({\n options: option.properties as OptionsSchema,\n isPlatformViz,\n requiredProps,\n subcategory: optionKey,\n }),\n };\n }\n } else {\n const { description, default: optionDefault } = option;\n const optionControl = getOptionControl(option, optionKey);\n const control = isPlatformViz ? { type: 'text' } : optionControl;\n const required = requiredProps.includes(optionKey);\n\n let defaultValue = optionDefault;\n if (!isPlatformViz && isDynamicOption(optionDefault as string)) {\n defaultValue = null;\n }\n\n argTypes[optionKey] = {\n description,\n control,\n name: optionKey,\n defaultValue,\n type: { required },\n optionType: optionControl.type,\n table: {\n type: { summary: getOptionDisplayType(option) },\n defaultValue: { summary: defaultValue },\n ...(subcategory && {\n category: 'Nested Options',\n subcategory,\n }),\n },\n };\n }\n });\n\n if (isPlatformViz) {\n Object.assign(argTypes, platformOptionArgTypes);\n }\n return argTypes;\n};\n\n/**\n * Helper which converts string visualization options to their required type\n * @param {any} value - option values\n * @param {string} expectedType - expected option type\n * @return {any} correctly typed option value\n */\nexport const transformOptionType = (value, expectedType = 'string'): any => {\n const isStringValue = !isDynamicOption(value) && isString(value);\n if (isStringValue && expectedType === 'boolean') return value == 'true';\n else if (isStringValue && expectedType === 'number') return toNumber(value);\n return value;\n};\n\n// stringify these fields for storybook controls' support\nconst FieldsToStringify = [\n 'layers',\n 'center',\n 'eventActions',\n 'fieldActions',\n 'legendLabels',\n 'lineDashStylesByField',\n 'seriesColors',\n 'seriesColorsByField',\n 'footerFields',\n 'highlightValuesByField',\n];\n\n/**\n * Helper which returns platform visualization options from Storybook controls\n * Utilizes argTypes to determine valid and nested options\n * @param {object} args - visualization story args\n * @param {ArgTypes} argTypes - visualization argTypes\n * @return {object} visualization options\n */\nexport const getOptionsFromArgTypes = (args: Record<string, any>, argTypes: ArgTypes): Record<string, any> =>\n reduce(\n argTypes,\n (accum, val, option) => {\n const subcategory = get(val, 'table.subcategory');\n const { optionType, defaultValue } = argTypes[option];\n let controlledOption = transformOptionType(get(args, option), optionType);\n // filter options from react & json if set to default value or is undefined\n if (optionType && controlledOption != null && controlledOption !== defaultValue) {\n // parse the value if option is stringified as part of flattenVizOptions\n if (FieldsToStringify.includes(option)) {\n try {\n controlledOption = JSON.parse(controlledOption);\n } catch (e) {\n controlledOption = null;\n }\n }\n if (subcategory) {\n if (!accum[subcategory]) accum[subcategory] = {};\n accum[subcategory][option] = controlledOption;\n } else accum[option] = controlledOption;\n }\n return accum;\n },\n { ...omit(args.options, Object.keys(argTypes)) }\n );\n\n/**\n * Helper which flattens objects single depth level\n * @param {object} options - visualization options object\n * @return {object} flattened visualization options\n */\nexport const flattenVizOptions = (options: Record<string, any>): Record<string, any> => {\n const nonFlattenOptions = new Set([\n 'y2Fields',\n 'overlayFields',\n 'gaugeRanges',\n 'fieldActions',\n 'highlightValuesByField',\n 'headers',\n ]);\n return reduce(\n options,\n (accum, val, option) => {\n if (!platformOptionArgTypes[option]) {\n if (typeof val === 'object' && FieldsToStringify.includes(option))\n accum[option] = JSON.stringify(val);\n else if (typeof val === 'object' && !nonFlattenOptions.has(option))\n accum = { ...accum, ...val };\n else accum[option] = val;\n }\n return accum;\n },\n {}\n );\n};\n/**\n * Returns value based on Storybook publishing status\n * @param {T} publishedStories - stories to include in published Storybook\n * @param {T} localStories - stories to include in local Storybook\n * @return {T} one of the two params\n */\nexport const getStoriesToInclude = <T>(publishedStories: T, localStories: T): T =>\n process.env.STORYBOOK_PUBLISH ? publishedStories : localStories;\n\n/**\n * Returns component level stories to include, defaults to innclude all stories\n * @param {StoriesList} stories - stories to include in published Storybook\n * @return {object} CSF includeStories config\n */\nexport const componentStoriesToInclude = (stories: StoriesList): object =>\n getStoriesToInclude({ includeStories: stories }, {});\n"],
4
+ "sourcesContent": ["import React from 'react';\nimport T from 'prop-types';\nimport isEmpty from 'lodash/isEmpty';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport Heading from '@splunk/react-ui/Heading';\nimport Markdown from '@splunk/react-ui/Markdown';\nimport styled from 'styled-components';\nimport { merge } from 'lodash';\nimport { getOptionDisplayType, getPatternOptions } from '../../.storybook/utils/storybookUtils';\n\nconst Option = styled.div`\n margin-top: 20px;\n`;\nconst OptionName = styled.div`\n color: #5ca300;\n padding-bottom: 5px;\n`;\nconst PairContainer = styled.div`\n margin-left: 40px;\n margin-top: 10px;\n`;\nconst PairTitle = styled.span`\n display: inline-block;\n color: #8293a7;\n width: 80px;\n`;\n\nconst PairValue = styled.span`\n font-family: 'Splunk Platform Mono', monospace;\n white-space: pre;\n`;\n\nconst PairValueJSON = styled.div`\n margin-left: 80px;\n pre {\n margin: 0;\n }\n code {\n font-size: 12px;\n font-family: 'Splunk Platform Mono', monospace;\n }\n`;\n\nconst PropertiesWrapper = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 0 : 40)}px;\n margin-top: 20px;\n`;\n\nconst PropertiesContainer = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 40 : 0)}px;\n margin-top: 10px;\n`;\n\nconst PropertiesContent = styled.div`\n margin-left: ${props => (props.isPatternProperty ? 40 : 0)}px;\n`;\n\n/**\n * @method isOneOfJsonSchema\n * @param {object} item\n * @returns {boolean}\n */\nconst isOneOfJsonSchema = item => item.oneOf && Array.isArray(item.oneOf);\n\n/**\n * get Or type as string\n * @method getOrType\n * @param {object} item\n * @param {string} res\n * @returns {string} res eg: (string | number)\n */\nconst getOrType = item => {\n let res = '';\n\n if (isOneOfJsonSchema(item)) {\n res = item.oneOf\n .map(one => {\n if (one.type !== 'array') {\n return one.type;\n }\n // eslint-disable-next-line no-use-before-define\n return getArrayType(one, '');\n })\n .join(' | ');\n } else if (Array.isArray(item.type)) {\n if (isEmpty(item.default)) {\n return item.type.join(' | ');\n }\n\n res = item.type.filter(itemType => itemType !== 'string').join(' | ');\n res += ' | ';\n res += `\"${item.default}\"`;\n }\n\n return res;\n};\n\n/**\n * get the array type as string\n * @method getArrayType\n * @param {object} item\n * @param {string} res\n * @returns {string} res eg: arrayOf(arrayOf(string | number | arrayOf(string | number)))\n */\nconst getArrayType = (item, res = '') => {\n if (item.type !== 'array') {\n if (Array.isArray(item.type) || isOneOfJsonSchema(item)) {\n return getOrType(item);\n }\n\n return item.type;\n }\n\n if (item.type === 'array') {\n res += 'arrayOf('; // eslint-disable-line no-param-reassign\n }\n res += getArrayType(item.items, ''); // eslint-disable-line no-param-reassign\n res += ')'; // eslint-disable-line no-param-reassign\n return res;\n};\n\n/**\n * get the type of this option item\n * @method getType\n * @param {ojbect} item option item\n * @returns {string} type\n */\nexport const getType = item => {\n if (isOneOfJsonSchema(item)) {\n return `oneOf(${getOrType(item)})`;\n }\n if (item.enum && Array.isArray(item.enum)) {\n const values =\n !isEmpty(item.enum) && typeof item.enum[0] === 'string'\n ? item.enum.map(v => `\"${v}\"`).join(', ')\n : item.enum.join(', ');\n\n return `oneOf([${values}])`;\n }\n\n if (Array.isArray(item.type)) {\n return getOrType(item);\n }\n\n if (item.type === 'array') {\n if ('items' in item) {\n return `arrayOf(${getType(item.items)})`;\n }\n return 'array';\n }\n return item.type;\n};\n\n/**\n * get the default value as string\n * @method getDefaultValue\n * @param {object | boolean | number | string} defaultValue\n * @returns {string | object[]} default value\n */\nconst getDefaultValue = defaultValue => {\n if (typeof defaultValue === 'boolean' || typeof defaultValue === 'number') {\n return defaultValue.toString();\n }\n if (Array.isArray(defaultValue)) {\n if (defaultValue.length > 1 && typeof defaultValue[0] === 'object') {\n // return the array only if the defaultValue is an object array\n return defaultValue;\n }\n const values = defaultValue.map(v => JSON.stringify(v)).join(', ');\n return `[${values}]`;\n }\n return defaultValue;\n};\n\nconst Pair = ({ title, content }) => (\n <PairContainer>\n <PairTitle>{`${title}:`}</PairTitle>\n {Array.isArray(content) ? (\n <PairValueJSON>\n <pre>\n <code>{JSON.stringify(content, null, 2)}</code>\n </pre>\n </PairValueJSON>\n ) : (\n <PairValue>{content}</PairValue>\n )}\n </PairContainer>\n);\n\nPair.propTypes = {\n title: T.string,\n content: T.oneOfType([T.string, T.arrayOf(T.object)]),\n};\n\nconst PropertyItems = ({ isPatternProperty = false, propsItems }) => (\n <PropertiesContainer isPatternProperty={isPatternProperty}>\n {isPatternProperty ? <PairTitle>{_('[fieldName]:')}</PairTitle> : null}\n <PropertiesContent isPatternProperty={isPatternProperty}>{propsItems}</PropertiesContent>\n </PropertiesContainer>\n);\n\nPropertyItems.propTypes = {\n isPatternProperty: T.bool,\n propsItems: T.array,\n};\n\nconst OptionItem = ({ name, type, desc, defaultValue, enumerable, PropertiesSection }) => (\n <Option>\n <OptionName>{name}</OptionName>\n {desc ? <Markdown style={{ marginLeft: 40 }} text={desc} /> : null}\n <Pair title={_('Type')} content={type} />\n {enumerable?.length > 0 && (\n <Pair\n title={_('oneOf')}\n content={`(${enumerable\n .map(\n entry =>\n `${typeof entry === 'string' ? '\"' : ''}${entry}${\n typeof entry === 'string' ? '\"' : ''\n }`\n )\n .join(' | ')})`}\n />\n )}\n {defaultValue && <Pair title={_('Default')} content={defaultValue} />}\n {PropertiesSection}\n </Option>\n);\n\nOptionItem.propTypes = {\n name: T.string,\n type: T.string,\n desc: T.string,\n enumerable: T.arrayOf(T.oneOfType([T.string, T.number])),\n defaultValue: T.oneOfType([T.string, T.arrayOf(T.object)]),\n PropertiesSection: T.element,\n};\n\nOptionItem.default = {\n PropertiesItem: null,\n};\n\nconst getPropertiesSection = (properties, patternProperties) => {\n let allProperties = [];\n let isPatternProperty = false;\n\n // the properties either comes from property field of the option schema item\n // or from the property field of each patternProperties of the option schema item\n // can check table tableFormat and columnFormat as examples\n if (!isEmpty(properties)) {\n allProperties = [properties];\n } else if (!isEmpty(patternProperties)) {\n Object.keys(patternProperties).forEach(patternKey => {\n const propsInPattern = patternProperties[patternKey].properties;\n if (propsInPattern) {\n allProperties.push(propsInPattern);\n }\n });\n\n isPatternProperty = true;\n }\n\n if (allProperties.length) {\n const allPropsItems = allProperties.map(props => {\n const propsItems = Object.keys(props).map(pKey => {\n const p = props[pKey];\n let pType = p.anyOf?.[0]\n ? getOptionDisplayType({ ...p.anyOf?.[0], enum: p.enum })\n : getOptionDisplayType({ ...p, enum: p.enum });\n const pDefault = getDefaultValue(p.default);\n\n let pEnumerable;\n // get nested oneOf property listing\n if (typeof p.anyOf?.[0]?.pattern === 'string') {\n pEnumerable = getPatternOptions(p.anyOf[0].pattern);\n } else if (p.anyOf?.[0]?.items?.enum?.length > 0) {\n // quick fix for nested `columnFormat` enumerables that replaces enums within brackets with raw JS types\n pType = pType.replace(/\\((.+?)\\)/g, 'string');\n pEnumerable = p.anyOf[0].items.enum;\n } else if (p.anyOf?.[0]?.items?.items?.enum?.length > 0) {\n // quick fix for nested `tableFormat` enumerables that replaces enums within brackets with raw JS types\n pType = pType.replace(/\\((.+?)\\)/g, 'string');\n pEnumerable = p.anyOf[0].items.items.enum;\n } else if (p.enum) {\n pEnumerable = p.enum;\n }\n\n // use the JS types (e.g. string, number) of the nested property if the nested property is an enumerable\n if (pEnumerable?.length) {\n pType = p.anyOf?.[0]?.type !== 'array' ? p.anyOf?.[0]?.type : pType;\n if (Array.isArray(pType)) {\n pType = pType.join(' | ');\n }\n }\n\n return (\n <OptionItem\n key={pKey}\n name={pKey}\n type={pType}\n enumerable={pEnumerable}\n desc={p.description}\n defaultValue={pDefault}\n />\n );\n });\n return (\n <PropertyItems\n key={propsItems}\n isPatternProperty={isPatternProperty}\n propsItems={propsItems}\n />\n );\n });\n\n return <PropertiesWrapper isPatternProperty={isPatternProperty}>{allPropsItems}</PropertiesWrapper>;\n }\n return null;\n};\n\nconst OptionsDoc = ({ options, description }) => (\n <div>\n {options.length === 0 ? (\n <Heading level={4}> No Options</Heading>\n ) : (\n <Heading level={4}>Options</Heading>\n )}\n {description && <div>{description}</div>}\n {Object.entries(options).map(([key, item]) => {\n let type;\n let enumerable = [];\n let PropertiesSection = null;\n\n // get oneOf property listing\n if (typeof item.anyOf?.[0]?.pattern === 'string') {\n enumerable = getPatternOptions(item.anyOf[0].pattern);\n } else if (item.anyOf?.[0]?.enum) {\n enumerable = item.anyOf?.[0]?.enum;\n } else if (item.enum) {\n enumerable = item.enum;\n }\n\n // get the nested options inside {option}.items.anyof. e.g. 'layers' in Map\n if (item.anyOf?.[0]?.type === 'array' && 'anyOf' in item.anyOf?.[0]?.items) {\n type = getOptionDisplayType(item);\n const { patternProperties } = item;\n // merge the 3 objects together instead of showing the longest options in the array\n const option = item.anyOf?.[0]?.items?.anyOf;\n const mergedOptions = option.reduce((prev, next) => merge(prev, next), {});\n const { properties } = mergedOptions;\n PropertiesSection = getPropertiesSection(properties, patternProperties);\n return (\n <OptionItem\n key={key}\n name={key}\n type={type}\n enumerable={enumerable}\n desc={item.description}\n PropertiesSection={PropertiesSection}\n />\n );\n }\n\n if (item.type === 'object') {\n // get properties for object type\n type = item.type;\n const { properties } = item;\n const { patternProperties } = item;\n PropertiesSection = getPropertiesSection(properties, patternProperties);\n } else if (enumerable?.length) {\n // use the JS types (e.g. string, number) of the property if the property is an enumerable\n type = item.anyOf?.[0]?.type;\n if (Array.isArray(type)) {\n type = type.join(' | ');\n }\n } else {\n type = getOptionDisplayType({ ...item.anyOf[0], enum: item.enum });\n }\n\n return (\n <OptionItem\n key={key}\n name={key}\n // item.anyOf in the config.ts is a tuple which holds [{ type, pattern, items }, { type, pattern: DYNAMIC_OPTIONS_PATTERN }]\n type={type}\n enumerable={enumerable}\n desc={item.description}\n defaultValue={getDefaultValue(item.default)}\n PropertiesSection={PropertiesSection}\n />\n );\n })}\n </div>\n);\n\nOptionsDoc.propTypes = {\n options: T.object.isRequired,\n description: T.string,\n};\n\nexport default OptionsDoc;\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"prop-types\";\nexport * from \"prop-types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash/isEmpty\";\nexport * from \"lodash/isEmpty\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Heading\";\nexport * from \"@splunk/react-ui/Heading\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Markdown\";\nexport * from \"@splunk/react-ui/Markdown\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/configUtils\";\nexport * from \"@splunk/visualizations-shared/configUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { get, omit, reduce, toNumber, isString } from 'lodash';\nimport type { OptionsSchema } from '@splunk/visualization-schemas';\nimport { isDynamicOption } from '@splunk/visualizations-shared/configUtils';\n\ninterface ArgTypeControl {\n type: string;\n options?: string[];\n min?: number;\n max?: number;\n}\n\nexport interface ArgTypeEntry {\n description?: string;\n control: ArgTypeControl;\n name: string;\n defaultValue?: any;\n type: { required: boolean };\n optionType: string;\n table: {\n type: { summary: string };\n defaultValue?: { summary: any };\n category?: string;\n subcategory?: string;\n disable?: boolean;\n };\n}\n\nexport interface ArgTypes {\n [key: string]: ArgTypeEntry;\n}\n\ntype StoriesList = RegExp | string[];\n\n/**\n * Returns type options from pattern\n * @example\n * // returns ['fixed', 'absolute', 'off']\n * getPatternOptions('\\$(\\w+:)?([^$|:]+?)(\\|[|\\w]+)?\\$|^fixed$|^absolute$|^off$')\n * @example\n * // returns []\n * getPatternOptions('^>.*')\n * @param {string} patternString - visualization option type pattern\n * @return {string[]} array of type options\n */\nexport const getPatternOptions = (patternString): string[] => {\n if (patternString.indexOf('^#[') === 0) {\n return patternString.slice(1).replace(/\\$/g, '').split('|^');\n }\n return patternString.replace(/\\$/g, '').split('|^').slice(1);\n};\n/**\n * Returns Storybook display type for an option\n * @param {object} option - visualization option\n * @return {string} Storybook display type\n */\nexport const getOptionDisplayType = (option): string => {\n const { oneOf, anyOf, type, enum: en, pattern, items } = option;\n let displayTypes: string[] = [];\n\n // wrap values in quotes only if enum or pattern is string\n const conditionalQuote = type === 'string' ? '\"' : '';\n if (en && Array.isArray(en)) {\n displayTypes = en.map(e => {\n const enumQuote = typeof e === 'string' ? '\"' : '';\n return `${enumQuote}${e}${enumQuote}`;\n });\n } else if (type === 'array' && items) {\n return `${getOptionDisplayType(items)}[]`;\n } else if (anyOf && Array.isArray(anyOf)) {\n return getOptionDisplayType(anyOf[0]);\n } else if (oneOf && Array.isArray(oneOf)) {\n displayTypes = oneOf.map(item => getOptionDisplayType(item));\n } else if (Array.isArray(type)) {\n displayTypes = type;\n } else if (pattern) {\n displayTypes = getPatternOptions(pattern).map(p => `${conditionalQuote}${p}${conditionalQuote}`);\n }\n\n if (displayTypes.length > 0) {\n return `(${displayTypes.join(' | ')})`;\n }\n return type;\n};\n\n/**\n * Returns Storybook control type for an option\n * @param {object} option - visualization option\n * @param {string} optionKey - visualization option key\n * @return {ArgTypeControl} Storybook control object\n */\nexport const getOptionControl = (option, optionKey): ArgTypeControl => {\n const { anyOf } = option;\n const schema = Array.isArray(anyOf) && anyOf.length ? anyOf[0] : option;\n\n const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n const { maximum, minimum, enum: en } = schema;\n\n const isColorOption = new RegExp(/color/, 'i').test(optionKey) && type !== 'array';\n\n if (isColorOption) {\n return { type: 'color' };\n } else if (en && Array.isArray(en)) {\n return { type: 'select', options: en };\n } else if (anyOf && type === 'string' && anyOf[0].pattern) {\n return { type: 'select', options: getPatternOptions(anyOf[0].pattern) };\n } else if (type === 'number' && (minimum || maximum)) {\n return {\n type: 'range',\n ...(typeof minimum === 'number' && { min: minimum }),\n ...(typeof maximum === 'number' && { max: maximum }),\n };\n } else if (type === 'string') {\n return { type: 'text' };\n }\n\n return { type };\n};\n\n/**\n * platform specific visualization option argTypes\n */\nconst objectTableControl = { control: { type: 'object' } };\nconst disableTableControl = { table: { disable: true } };\nexport const platformOptionArgTypes = {\n context: objectTableControl,\n dataSources: objectTableControl,\n dataSource: disableTableControl,\n options: disableTableControl,\n onEventTrigger: { action: 'eventTrigger', ...disableTableControl },\n hasEventHandlers: disableTableControl,\n};\n\n/**\n * Returns formatted Storybook argTypes for a visualization from its options schema\n * @param {OptionsSchema} options - visualization options\n * @param {string[]} requiredProps - required visualization props\n * @param {boolean} isPlatformViz - indicates if pure or platform visualization\n * @param {string} subcategory - nested property parent option name\n * @return {ArgTypes} Storybook argTypes\n */\nexport const optionsSchemaToArgTypes = ({\n options = {},\n requiredProps = [],\n isPlatformViz = false,\n subcategory = null,\n}: {\n options: OptionsSchema;\n requiredProps: string[];\n isPlatformViz?: boolean;\n subcategory?: string;\n}): ArgTypes => {\n const validObjectTypeOptions = [\n 'lineDashStylesByField',\n 'seriesColorsByField',\n 'fieldActions',\n 'highlightValuesByField',\n ];\n let argTypes: ArgTypes = {};\n Object.keys(options).forEach(optionKey => {\n const option = get(options, optionKey);\n if (option.type === 'object' && !validObjectTypeOptions.includes(optionKey)) {\n // do not support controls for patternProperties, only nested properties\n if (option.properties) {\n argTypes = {\n ...argTypes,\n ...optionsSchemaToArgTypes({\n options: option.properties as OptionsSchema,\n isPlatformViz,\n requiredProps,\n subcategory: optionKey,\n }),\n };\n }\n } else {\n const { description, default: optionDefault } = option;\n const optionControl = getOptionControl(option, optionKey);\n const control = isPlatformViz ? { type: 'text' } : optionControl;\n const required = requiredProps.includes(optionKey);\n\n let defaultValue = optionDefault;\n if (!isPlatformViz && isDynamicOption(optionDefault as string)) {\n defaultValue = null;\n }\n\n argTypes[optionKey] = {\n description,\n control,\n name: optionKey,\n defaultValue,\n type: { required },\n optionType: optionControl.type,\n table: {\n type: { summary: getOptionDisplayType(option) },\n defaultValue: { summary: defaultValue },\n ...(subcategory && {\n category: 'Nested Options',\n subcategory,\n }),\n },\n };\n }\n });\n\n if (isPlatformViz) {\n Object.assign(argTypes, platformOptionArgTypes);\n }\n return argTypes;\n};\n\n/**\n * Helper which converts string visualization options to their required type\n * @param {any} value - option values\n * @param {string} expectedType - expected option type\n * @return {any} correctly typed option value\n */\nexport const transformOptionType = (value, expectedType = 'string'): any => {\n const isStringValue = !isDynamicOption(value) && isString(value);\n if (isStringValue && expectedType === 'boolean') return value == 'true';\n else if (isStringValue && expectedType === 'number') return toNumber(value);\n return value;\n};\n\n// stringify these fields for storybook controls' support\nconst FieldsToStringify = [\n 'layers',\n 'center',\n 'eventActions',\n 'fieldActions',\n 'legendLabels',\n 'lineDashStylesByField',\n 'seriesColors',\n 'additionalTooltipFields',\n 'seriesColorsByField',\n 'footerFields',\n 'highlightValuesByField',\n];\n\n/**\n * Helper which returns platform visualization options from Storybook controls\n * Utilizes argTypes to determine valid and nested options\n * @param {object} args - visualization story args\n * @param {ArgTypes} argTypes - visualization argTypes\n * @return {object} visualization options\n */\nexport const getOptionsFromArgTypes = (args: Record<string, any>, argTypes: ArgTypes): Record<string, any> =>\n reduce(\n argTypes,\n (accum, val, option) => {\n const subcategory = get(val, 'table.subcategory');\n const { optionType, defaultValue } = argTypes[option];\n let controlledOption = transformOptionType(get(args, option), optionType);\n // filter options from react & json if set to default value or is undefined\n if (optionType && controlledOption != null && controlledOption !== defaultValue) {\n // parse the value if option is stringified as part of flattenVizOptions\n if (FieldsToStringify.includes(option)) {\n try {\n controlledOption = JSON.parse(controlledOption);\n } catch (e) {\n controlledOption = null;\n }\n }\n if (subcategory) {\n if (!accum[subcategory]) accum[subcategory] = {};\n accum[subcategory][option] = controlledOption;\n } else accum[option] = controlledOption;\n }\n return accum;\n },\n { ...omit(args.options, Object.keys(argTypes)) }\n );\n\n/**\n * Helper which flattens objects single depth level\n * @param {object} options - visualization options object\n * @return {object} flattened visualization options\n */\nexport const flattenVizOptions = (options: Record<string, any>): Record<string, any> => {\n const nonFlattenOptions = new Set([\n 'y2Fields',\n 'overlayFields',\n 'gaugeRanges',\n 'fieldActions',\n 'highlightValuesByField',\n 'headers',\n ]);\n return reduce(\n options,\n (accum, val, option) => {\n if (!platformOptionArgTypes[option]) {\n if (typeof val === 'object' && FieldsToStringify.includes(option))\n accum[option] = JSON.stringify(val);\n else if (typeof val === 'object' && !nonFlattenOptions.has(option))\n accum = { ...accum, ...val };\n else accum[option] = val;\n }\n return accum;\n },\n {}\n );\n};\n/**\n * Returns value based on Storybook publishing status\n * @param {T} publishedStories - stories to include in published Storybook\n * @param {T} localStories - stories to include in local Storybook\n * @return {T} one of the two params\n */\nexport const getStoriesToInclude = <T>(publishedStories: T, localStories: T): T =>\n process.env.STORYBOOK_PUBLISH ? publishedStories : localStories;\n\n/**\n * Returns component level stories to include, defaults to innclude all stories\n * @param {StoriesList} stories - stories to include in published Storybook\n * @return {object} CSF includeStories config\n */\nexport const componentStoriesToInclude = (stories: StoriesList): object =>\n getStoriesToInclude({ includeStories: stories }, {});\n"],
5
5
  "mappings": "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",
6
6
  "names": ["defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/common/utils/mapUtils.ts", "esm-externals:@splunk/visualization-encoding/utils/types", "esm-externals:@splunk/visualization-encoding/utils/dsl", "esm-externals:@splunk/visualizations-shared/hocUtils", "esm-externals:@splunk/visualizations-shared/JSONSchemaUtils", "esm-externals:react", "esm-externals:styled-components", "esm-externals:lodash", "esm-externals:@splunk/visualizations-shared/colorUtils", "esm-externals:d3-scale", "esm-externals:chroma-js", "esm-externals:@splunk/visualization-color-palettes", "esm-externals:@splunk/visualization-schemas", "../../src/Map/PureMap/MapUtils.ts", "esm-externals:maplibre-gl", "esm-externals:@splunk/react-ui/Popover", "esm-externals:@splunk/ui-utils/i18n", "../../src/Map/PureMap/Tooltip.tsx", "../../src/Map/PureMap/MarkerWrapper.tsx", "../../src/Map/PureMap/BubbleLayer.tsx"],
4
- "sourcesContent": ["import { isNumber } from '@splunk/visualization-encoding/utils/types';\nimport { getFieldsFromDSL } from '@splunk/visualization-encoding/utils/dsl';\nimport { deepMergeWithArrayPrimitiveOverrides } from '@splunk/visualizations-shared/hocUtils';\nimport { pickFieldFromJSONSchema } from '@splunk/visualizations-shared/JSONSchemaUtils';\nimport { GEO_LAT_AND_LONG_FIELD } from '../../Map/PureMap/BubbleLayer';\n\nexport const columnsNullToZeros = (config, dataSources, options) => {\n const { primary } = dataSources;\n const { columns, fields } = primary.data;\n let newColumns = columns;\n const mergedOptions = deepMergeWithArrayPrimitiveOverrides(\n {},\n options,\n pickFieldFromJSONSchema(config.optionsSchema, 'default')\n );\n if (mergedOptions.layers?.[0]?.type === 'bubble') {\n const latitudeField = getFieldsFromDSL(mergedOptions.layers[0].latitude, dataSources)[0] || '';\n const longitudeField = getFieldsFromDSL(mergedOptions.layers[0].longitude, dataSources)[0] || '';\n const excludedFields = [latitudeField, longitudeField, 'geobin'].concat(GEO_LAT_AND_LONG_FIELD);\n const indicesToEvaluate = new Set(\n fields.reduce((arr, e, i) => {\n const field = typeof e === 'string' ? e : e.name.toString();\n if (!excludedFields.includes(field)) {\n arr.push(i);\n }\n return arr;\n }, [])\n );\n\n newColumns = columns.map((column, i) => {\n if (indicesToEvaluate.has(i)) {\n // sanitize value and convert string to numeric numbers\n return column.map(value => (!value || !isNumber(value) ? 0 : +value));\n }\n return column;\n });\n }\n\n const modifiedDatasources = {\n ...dataSources,\n primary: {\n ...primary,\n data: {\n ...primary.data,\n columns: newColumns,\n },\n },\n };\n\n return modifiedDatasources;\n};\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/utils/types\";\nexport * from \"@splunk/visualization-encoding/utils/types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/utils/dsl\";\nexport * from \"@splunk/visualization-encoding/utils/dsl\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/hocUtils\";\nexport * from \"@splunk/visualizations-shared/hocUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport * from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/colorUtils\";\nexport * from \"@splunk/visualizations-shared/colorUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"d3-scale\";\nexport * from \"d3-scale\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"chroma-js\";\nexport * from \"chroma-js\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-color-palettes\";\nexport * from \"@splunk/visualization-color-palettes\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-schemas\";\nexport * from \"@splunk/visualization-schemas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { forEach, sum, isNumber, min as lodashMin, max as lodashMax, get, isEqual, isObject } from 'lodash';\nimport { LngLatBoundsLike } from 'maplibre-gl';\nimport { scalePow } from 'd3-scale';\nimport chroma from 'chroma-js';\nimport type { MapContextInterface, BaseTileConfig } from '@splunk/visualization-context/MapContext';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport { VIZ_CATEGORICAL } from '@splunk/visualization-color-palettes';\nimport { isNumber as isNumberUtil } from '@splunk/visualization-encoding/utils/types';\nimport type { GeoJsonDataType } from '@splunk/visualizations-shared/mapUtils';\nimport { LAYER_TYPE } from '@splunk/visualization-schemas';\n\nexport const MAX_LATITUDE = 90;\nexport const MIN_LATITUDE = -90;\nexport const MAX_LONGITUDE = 180;\nexport const MIN_LONGITUDE = -180;\nexport const DEFAULT_RESULT_LIMIT = 1000;\nexport const DEFAULT_CLUSTER_COLOR = '#909090';\nexport const DEFAULT_SERIES_COLORS = VIZ_CATEGORICAL;\n// MapLibre requires a map style specification number which is always 8\nexport const MAP_STYLE_VERSION_NUMBER = 8;\n// currently using one [min, max] value set for bubbles across all zoom levels\n// TODO: design choices on [min, max] bubble size for different zoom levels\nexport const MIN_BUBBLE_RADIUS = 7.11; // 10px\nexport const MAX_BUBBLE_RADIUS = 45.26; // 85px\nexport const DEFAULT_OPACITY = 0.8;\nconst LONGITUDE = 'longitude';\nconst LATITUDE = 'latitude';\ninterface GenericLayerType {\n type: string;\n latitude: number[];\n longitude: number[];\n dataColors?: string[];\n seriesColors: string[];\n additionalTooltipFields?: string[];\n resultLimit: number;\n metadata?: Array<{ [key: string]: number | string }>;\n}\n\nexport interface MarkerLayerType extends GenericLayerType {\n type: LAYER_TYPE.Marker;\n}\n\nexport interface BubbleLayerType extends GenericLayerType {\n type: LAYER_TYPE.Bubble;\n bubbleSize?: number[][] | number[];\n bubbleSizeFields: string[];\n geobin?: string[];\n}\n\ninterface BubbleLayerDatumType {\n zoom: number;\n values: number[];\n sanitizedValues: number[];\n coordinates: number[];\n}\n\nexport interface BubbleLayerDataType {\n data: BubbleLayerDatumType[];\n dataRange: number[];\n isPie: boolean;\n resultLimit: number;\n bubbleSizeFields: string[];\n}\n\nexport interface ChoroplethLayerType {\n type: LAYER_TYPE.Choropleth;\n areaIds: string[];\n areaValues: number[];\n dataColors: string[];\n additionalTooltipFields?: string[];\n geom?: GeoJsonDataType[];\n resultLimit?: number;\n metadata?: Array<{ [key: string]: number | string | GeoJsonDataType }>;\n source?: string;\n width?: string | number;\n height?: string | number;\n choroplethEmptyAreaColor?: string;\n choroplethStrokeColor?: string;\n choroplethOpacity?: number;\n}\n\n// todo(@ssahnoune) - look into this\nexport interface MapLayerClickPayloadType {\n name?: string;\n value?: string | number;\n /* cell values of all cells of clicked row with the field and value - in shape row.<field>.value */\n [key: string]: string | number;\n}\n\nexport type ClusterLayerType = BubbleLayerType | MarkerLayerType;\nexport type LayerType = ClusterLayerType | ChoroplethLayerType;\n/**\n * Construct a tile preset {key: config} by combining the default + custom tile configs\n * Also returns the default tile config for each theme - light/dark\n * @param {MapContextInterface} args\n * @param {BaseTileConfig[]} args.defaultTileConfig\n * @param {BaseTileConfig[]} args.customTileConfig\n * @returns {Object} tile preset\n */\nexport const getTilePreset = ({\n defaultTileConfig = [],\n customTileConfig = [],\n}: MapContextInterface): {\n tilePreset: Record<string, BaseTileConfig>;\n defaultTileLight: BaseTileConfig;\n defaultTileDark: BaseTileConfig;\n} => {\n const tilePreset = {};\n let defaultTileLight = {};\n let defaultTileDark = {};\n const tileConfigs = [].concat(defaultTileConfig).concat(customTileConfig);\n forEach(tileConfigs, tileConfig => {\n const key = tileConfig?.key;\n const updatedConfig = { theme: 'all', ...tileConfig, version: MAP_STYLE_VERSION_NUMBER };\n tilePreset[key] = updatedConfig;\n });\n\n if (defaultTileConfig.length > 0) {\n defaultTileLight =\n defaultTileConfig.find(config => config.theme === 'light') ??\n defaultTileConfig.find(config => config.theme === undefined);\n defaultTileDark =\n defaultTileConfig.find(config => config.theme === 'dark') ??\n defaultTileConfig.find(config => config.theme === undefined);\n }\n\n return { tilePreset, defaultTileLight, defaultTileDark };\n};\n\n/**\n * Check if baseLayerTileServer is in tilePreset and config matches current theme, if yes, return.\n * If no, construct a mapStyle with baseLayerTilerServer and baseLayerTileServerType\n * Else return default tile config based on current theme\n * @param {Object} args\n * @param {BaseTileConfig[]} args.tilePreset\n * @param {String} args.baseLayerTilerServer\n * @param {String} args.baseLayerTileServerType\n * @param {String} args.colorScheme\n * @param {BaseTileConfig} args.defaultTileDark\n * @param {BaseTileConfig} args.defaultTileLight\n * @returns {BaseTileConfig} mapStyle\n */\nexport const getMapStyle = ({\n showBaseLayer,\n baseLayerTileServer = '',\n baseLayerTileServerType = '',\n tilePreset = {},\n colorScheme = 'light',\n defaultTileLight = {},\n defaultTileDark = {},\n}: {\n showBaseLayer: boolean;\n baseLayerTileServer?: string;\n baseLayerTileServerType?: string;\n tilePreset?: Record<string, BaseTileConfig>;\n colorScheme?: string;\n defaultTileLight?: BaseTileConfig;\n defaultTileDark?: BaseTileConfig;\n}): BaseTileConfig => {\n if (!showBaseLayer) {\n return {\n version: MAP_STYLE_VERSION_NUMBER,\n sources: {\n 'base-tiles': {\n type: 'raster',\n tiles: [\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',\n ],\n tileSize: 256,\n },\n },\n layers: [\n {\n id: 'base-layer',\n type: 'raster',\n source: 'base-tiles',\n minzoom: 0,\n maxzoom: 22,\n },\n ],\n };\n }\n\n if (\n baseLayerTileServer &&\n tilePreset[baseLayerTileServer] &&\n (tilePreset[baseLayerTileServer].theme === colorScheme ||\n tilePreset[baseLayerTileServer].theme === 'all')\n ) {\n return tilePreset[baseLayerTileServer];\n }\n\n if (baseLayerTileServer && baseLayerTileServerType) {\n let tiles = [];\n /**\n * Tile Server URLs (eg: http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png) can specify the variable {s} which refers to a subdomain\n * Subdomains are used to help with browser parallel requests per domain limitation. These subdomains are typically single letters 'a', 'b' and 'c'\n * Refer to https://leafletjs.com/SlavaUkraini/reference.html#tilelayer and https://wiki.openstreetmap.org/wiki/Tile_servers\n */\n if (baseLayerTileServer.match(/^(https?):\\/\\/{(s|S)}\\../)) {\n /**\n * sXML (Leaflet) allows users to define their own tile server URLs + list of available subdomains\n * In order to preserve this behavior during conversion to splunk.map,\n * if the variable {s} or {S} is detected, replace it with 'a', 'b' and 'c' - default values for subdomains\n * TODO: in the future, add an additional prop - baseLayerTileServerSubdomains: ['x', 'y', 'z'], default being ['a', 'b', 'c']\n */\n tiles = [\n baseLayerTileServer.replace(/{(s|S)}/, 'a'),\n baseLayerTileServer.replace(/{(s|S)}/, 'b'),\n baseLayerTileServer.replace(/{(s|S)}/, 'c'),\n ];\n } else {\n tiles = [baseLayerTileServer];\n }\n // TODO: remove hardcoded style when we allow users to pass in layer style through Viz options\n const mapStyle = {\n version: MAP_STYLE_VERSION_NUMBER,\n sources: {\n 'base-tiles': {\n type: baseLayerTileServerType,\n tiles,\n tileSize: 256,\n },\n },\n layers: [\n {\n id: 'base-layer',\n type: 'raster',\n source: 'base-tiles',\n minzoom: 0,\n maxzoom: 24, // https://maplibre.org/maplibre-gl-js-docs/api/map/\n },\n ],\n };\n return mapStyle;\n }\n\n // if tile server is not present in the preset AND we can't construct a mapStyle, fall back on defaults\n return colorScheme === 'light' ? defaultTileLight : defaultTileDark;\n};\n\nexport interface ZoomConstraints {\n minZoom: number;\n maxZoom: number;\n}\n\nexport const getZoomConstraintsFromTileConfig = (\n tileConfig: BaseTileConfig,\n baseLayerTileServer?: string\n): ZoomConstraints => {\n const { sources, layers } = tileConfig;\n let matchedBaseLayerTileServer = false;\n // check sources for minzoom maxzoom first\n const sourceKeys = Object.keys(sources);\n for (let i = 0; i < sourceKeys.length; i += 1) {\n const { minzoom, maxzoom } = sources[sourceKeys[i]];\n if (baseLayerTileServer && sources[sourceKeys[i]].tiles.indexOf(baseLayerTileServer) !== -1) {\n matchedBaseLayerTileServer = true;\n }\n if (\n ((baseLayerTileServer && matchedBaseLayerTileServer) || !baseLayerTileServer) &&\n isNumber(minzoom) &&\n isNumber(maxzoom)\n ) {\n return {\n minZoom: minzoom,\n maxZoom: maxzoom,\n };\n }\n }\n // then check layers\n for (let i = 0; i < layers.length; i += 1) {\n const { minzoom, maxzoom } = layers[i];\n if (\n ((baseLayerTileServer && matchedBaseLayerTileServer) || !baseLayerTileServer) &&\n isNumber(minzoom) &&\n isNumber(maxzoom)\n ) {\n return {\n minZoom: minzoom,\n maxZoom: maxzoom,\n };\n }\n }\n // Maplibre default - would reset previous min/maxZoom https://maplibre.org/maplibre-gl-js-docs/api/map/\n return {\n minZoom: 0,\n maxZoom: 24,\n };\n};\n\nexport const getZoomLevelFromGeobin = (geobinStr: string): number => {\n if (!geobinStr) {\n return null;\n }\n // geostats cmds return geobin with zoom level 0-18, 0-99 in the geobinPattern covers the range\n const geobinPattern = /bin_id_zl_([0-9]{0,2})?_y_/g;\n const match = geobinPattern.exec(geobinStr);\n return (match?.length && parseInt(match[1], 10)) ?? null;\n};\n\n// Bubble colors - static\nexport const getStaticColors = (colorCount: number, colorArray: string[]): string[] => {\n if (colorCount < 0 || !colorCount) {\n return [DEFAULT_CLUSTER_COLOR];\n }\n if (!colorArray || !colorArray.length) {\n return [...Array(colorCount).keys()].map(i => DEFAULT_SERIES_COLORS[i]);\n }\n // loop through colorArray to pick the first $colorCount colors\n // start from begining again if colorCount > colorArray.length\n return [...Array(colorCount).keys()].map(i =>\n isColor(colorArray[i % colorArray.length]) ? colorArray[i % colorArray.length] : DEFAULT_CLUSTER_COLOR\n );\n};\n\n// Bubble size\nexport const matchBubbleSize = (dataRange: number[], data: number): any => {\n const size = scalePow().exponent(0.2).domain(dataRange).range([MIN_BUBBLE_RADIUS, MAX_BUBBLE_RADIUS])(\n data\n );\n\n if (size > MAX_BUBBLE_RADIUS) {\n return MAX_BUBBLE_RADIUS;\n }\n if (size < MIN_BUBBLE_RADIUS) {\n return MIN_BUBBLE_RADIUS;\n }\n return size;\n};\n\nexport const transposeArray = (array: number[][]): number[][] => {\n if (!array || !array.length || !array[0] || !array[0].length) {\n return [];\n }\n return array[0].map((_, i) => array.map(row => row[i]));\n};\n\n// sanitize values: update all null, undefined, or negative values to 0\nexport const sanitizeValues = (values: number[] | number[][]) => {\n // null / undefined\n if (!values) {\n return 0;\n }\n // number\n if (!Array.isArray(values)) {\n return values > 0 ? values : 0;\n }\n // array\n return values.map(arr => sanitizeValues(arr));\n};\n\nexport const bakeBubbleData = (layer: BubbleLayerType): BubbleLayerDataType => {\n if (\n !layer ||\n !layer.bubbleSize?.length ||\n !layer.geobin ||\n !layer.geobin.length ||\n !layer.latitude ||\n !layer.latitude.length ||\n !layer.longitude ||\n !layer.longitude.length\n ) {\n return null;\n }\n // if bubbleSize is passed as an array of single number array (data series)\n // e.g. [value0, value1, ...]\n // format each value as an array to unify data operations for data series and frames\n const sanitizedBubbleSize = sanitizeValues(layer.bubbleSize);\n let transposedBubbleSize: number[][];\n let transposedSanitizedBubbleSize: number[][];\n let isPie = false;\n // format array if bubbleSize is passed as an array of array (data frame)\n if (Array.isArray(layer.bubbleSize[0])) {\n // one-time array transpose,\n // e.g. from [column0data, column0data] (multi series)\n // to [[column0datum0, column1datum0], [column0datum1, column1data1], ...]\n // or e.g. from [column0data] (single series)\n // to [[column0data]]\n // for easy access of values at each geo location,\n // and min max pie size computation\n transposedBubbleSize = transposeArray(layer.bubbleSize as number[][]);\n transposedSanitizedBubbleSize = transposeArray(sanitizedBubbleSize);\n // if multiple series in the dataframe, set isPie to true\n if (layer.bubbleSize.length > 1) {\n isPie = true;\n }\n } else {\n transposedBubbleSize = layer.bubbleSize.map(n => [n]);\n transposedSanitizedBubbleSize = sanitizedBubbleSize.map(n => [n]);\n }\n if (!transposedBubbleSize || !transposedBubbleSize.length) {\n return null;\n }\n const data = layer.latitude\n .map((lat, i) => ({\n zoom: getZoomLevelFromGeobin(layer.geobin[i]),\n values: transposedBubbleSize[i],\n sanitizedValues: transposedSanitizedBubbleSize[i],\n coordinates: [layer.longitude[i], lat],\n metadata: layer.metadata ? layer.metadata[i] : {},\n }))\n .filter(d => Boolean(d.values));\n\n // compute the min/max value to encode min/max pie or bubble size\n let min = sum(transposedSanitizedBubbleSize[0]);\n let max = sum(transposedSanitizedBubbleSize[1]);\n transposedSanitizedBubbleSize.forEach(row => {\n const bubbleSize = sum(row);\n max = bubbleSize > max ? bubbleSize : max;\n min = bubbleSize < min ? bubbleSize : min;\n });\n return {\n data,\n dataRange: [min, max],\n isPie,\n resultLimit: layer.resultLimit,\n bubbleSizeFields: layer.bubbleSizeFields,\n };\n};\n\nexport const isValidLatLon = (latlon: Array<number | string>): boolean => {\n if (!latlon || !Array.isArray(latlon) || latlon.length !== 2) {\n return false;\n }\n const [lat, lon] = latlon;\n if (!isNumberUtil(lat) || !(lat >= MIN_LATITUDE && lat <= MAX_LATITUDE)) {\n return false;\n }\n if (!isNumberUtil(lon) || !(lon >= MIN_LONGITUDE && lon <= MAX_LONGITUDE)) {\n return false;\n }\n return true;\n};\n\n/**\n * Returns a list of all lat or lon coordinates used in a specified layer\n * @param {LayerType[]} layer\n * @param {string} field\n * @returns {number[]} list of lat coordinates or lon coordinates\n */\nconst getLatOrLonCoordinates = (layer: LayerType, field: string): number[] => {\n const getClusterValues = (clusterLayer: ClusterLayerType): number[] =>\n get(clusterLayer, field, []).slice(\n 0,\n clusterLayer.type === LAYER_TYPE.Marker && clusterLayer.resultLimit\n ? clusterLayer.resultLimit\n : DEFAULT_RESULT_LIMIT\n );\n\n const getChoroplethValues = (choroplethLayer: ChoroplethLayerType): number[] => {\n const slicedGeomList = choroplethLayer.geom.slice(0, choroplethLayer.resultLimit);\n const flatCoordinates = slicedGeomList.flatMap(geomObject => geomObject.coordinates.flat(2));\n return flatCoordinates.map(coord => coord[field === LONGITUDE ? 0 : 1]);\n };\n\n return layer.type === LAYER_TYPE.Choropleth\n ? getChoroplethValues(layer as ChoroplethLayerType)\n : getClusterValues(layer as ClusterLayerType);\n};\n\n/**\n * Returns the min and max LongLat pairs to determine the layer boundaries to fit all markers/bubbles\n * @param {LayerType[]} layers\n * @returns {LngLatBoundsLike}\n */\nexport const getGlobalLayerBoundaries = (layers: LayerType[]): LngLatBoundsLike => {\n const isLayerValid = (field: string): boolean =>\n layers.every(layer => layer[field] || (layer as ChoroplethLayerType).geom);\n const getDefaultMax = (field: string) => (field === LONGITUDE ? MAX_LONGITUDE : MAX_LATITUDE);\n const getDefaultMin = (field: string) => (field === LONGITUDE ? MIN_LONGITUDE : MIN_LATITUDE);\n\n if (!layers || !Array.isArray(layers) || !layers.length) {\n return null;\n }\n\n const getMin = (field: string): number => {\n if (!isLayerValid(field)) {\n return getDefaultMin(field);\n }\n return layers.reduce((prevVal, layer) => {\n const coordinatesNumArr = getLatOrLonCoordinates(layer, field).map(x => +x);\n return lodashMin([prevVal, ...coordinatesNumArr]);\n }, getDefaultMax(field));\n };\n\n const getMax = (field: string): number => {\n if (!isLayerValid(field)) {\n return getDefaultMax(field);\n }\n return layers.reduce((prevVal, layer) => {\n const coordinatesNumArr = getLatOrLonCoordinates(layer, field).map(Number);\n return lodashMax([prevVal, ...coordinatesNumArr]);\n }, getDefaultMin(field));\n };\n\n return [\n [getMin(LONGITUDE), getMin(LATITUDE)],\n [getMax(LONGITUDE), getMax(LATITUDE)],\n ];\n};\n\nexport const getScaledOpacities = (colors: string[], cfgOpacity: number): number[] => {\n // extract opacity information from 8 digit hex codes\n const opacities = colors?.map(color => (color?.length === 9 ? chroma(color).alpha() ?? 1 : 1));\n // opacity cannot be greater than configured opacity\n return opacities?.map(opacity => opacity * cfgOpacity);\n};\n\nexport const compareBaseStyles = (curr, next): boolean => {\n const currBaseLayer = curr?.layers?.find(layer => layer?.id === 'base-layer');\n const nextBaseLayer = next?.layers?.find(layer => layer?.id === 'base-layer');\n const currBaseSource = get(curr?.sources, (currBaseLayer?.source as string) ?? '');\n const nextBaseSource = get(next?.sources, (nextBaseLayer?.source as string) ?? '');\n\n if (!currBaseLayer || !nextBaseLayer || !currBaseSource || !nextBaseSource) {\n return false;\n }\n\n return isEqual(currBaseLayer, nextBaseLayer) && isEqual(currBaseSource, nextBaseSource);\n};\n\nexport const formatMetadata = (\n choroplethLayer: ChoroplethLayerType,\n i: number\n): { [key: string]: string } => {\n if (!choroplethLayer || !choroplethLayer.areaIds || !choroplethLayer.areaValues) return {};\n if (i >= choroplethLayer.areaIds.length) return {};\n\n const metadata = choroplethLayer.metadata ? choroplethLayer.metadata[i] : {};\n const name = choroplethLayer.areaIds[i];\n const value = choroplethLayer.areaValues[i];\n const base = { name, value: String(value) };\n\n return Object.keys(metadata).reduce((result, curr) => {\n const key = `row.${curr}.value`;\n const val = isObject(metadata[curr]) ? JSON.stringify(metadata[curr]) : String(metadata[curr]);\n return { ...result, [key]: val };\n }, base);\n};\n", "\nimport * as defaultImport from \"maplibre-gl\";\nexport * from \"maplibre-gl\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Popover\";\nexport * from \"@splunk/react-ui/Popover\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport Popover from '@splunk/react-ui/Popover';\nimport { _ } from '@splunk/ui-utils/i18n';\n\nconst StyledPopover = styled(Popover)`\n width: 250px;\n font-size: 12px;\n`;\n\nconst StyledTable = styled.table`\n margin: 2px 6px 2px 6px;\n width: calc(100% - 12px);\n`;\n\nconst StyledTitleColumn = styled.td`\n opacity: 0.85;\n`;\n\nconst StyledValueColumn = styled.td`\n text-align: right;\n`;\n\nconst StyledColorBlock = styled.div`\n background-color: ${props => props.color};\n display: inline-block;\n margin-right: 4px;\n border-radius: 2px;\n width: 6px;\n height: 11px;\n transform: translateY(1px);\n`;\n\nexport const convertDegToDMS = (decimalDegree: number, type: 'latitude' | 'longitude'): string => {\n const truncate = n => (n > 0 ? Math.floor(n) : Math.ceil(n));\n const absoluteDegree = Math.abs(decimalDegree);\n let degrees = truncate(absoluteDegree);\n let minutes = truncate((absoluteDegree - degrees) * 60);\n let seconds = Math.round((absoluteDegree - degrees - minutes / 60) * 3600);\n if (seconds === 60) {\n minutes += 1;\n seconds = 0;\n }\n if (minutes === 60) {\n degrees += 1;\n minutes = 0;\n }\n let direction: string;\n if (type === 'longitude') {\n direction = decimalDegree < 0 ? 'W' : 'E';\n } else if (type === 'latitude') {\n direction = decimalDegree < 0 ? 'S' : 'N';\n }\n return `${degrees}\u00B0 ${minutes}' ${seconds}\" ${direction}`;\n};\n\nexport interface TooltipProps {\n open?: boolean;\n anchor?: HTMLElement;\n latitude?: number;\n longitude?: number;\n areaId?: string;\n areaValue?: number;\n additionalFields?: Array<{ name: string; value: number | string; color?: string }>;\n}\n// only want latitude/longitude for marker and bubble\n// omit for choropleth, and put areaid, areavalue instead\nconst Tooltip = ({\n open,\n anchor,\n latitude,\n longitude,\n areaId,\n areaValue,\n additionalFields = [],\n}: TooltipProps): JSX.Element => (\n <StyledPopover\n open={open}\n animation={false}\n anchor={anchor}\n data-test=\"map-marker-tooltip\"\n defaultPlacement=\"above\"\n >\n <StyledTable>\n <tbody>\n {areaId && areaValue && (\n <tr>\n <StyledTitleColumn data-test=\"area-id\">{areaId}</StyledTitleColumn>\n <StyledValueColumn data-test=\"area-value\">{areaValue}</StyledValueColumn>\n </tr>\n )}\n {latitude && (\n <tr>\n <StyledTitleColumn>{_('Latitude')}</StyledTitleColumn>\n <StyledValueColumn data-test=\"latitude\">\n {convertDegToDMS(latitude, 'latitude')}\n </StyledValueColumn>\n </tr>\n )}\n {longitude && (\n <tr>\n <StyledTitleColumn>{_('Longitude')}</StyledTitleColumn>\n <StyledValueColumn data-test=\"longitude\">\n {convertDegToDMS(longitude, 'longitude')}\n </StyledValueColumn>\n </tr>\n )}\n {additionalFields\n .filter(({ value }) => value && String(value) !== '0')\n .map(({ name, value, color }, index) => (\n <tr key={String(index)}>\n <StyledTitleColumn data-test=\"field-title\">\n {color ? <StyledColorBlock data-test=\"field-color\" color={color} /> : null}\n {name}\n </StyledTitleColumn>\n <StyledValueColumn data-test=\"field-value\">{value}</StyledValueColumn>\n </tr>\n ))}\n </tbody>\n </StyledTable>\n </StyledPopover>\n);\n\nexport default Tooltip;\n", "import type { Map } from 'maplibre-gl';\nimport { Marker } from 'maplibre-gl';\nimport * as React from 'react';\nimport type { TooltipProps } from './Tooltip';\nimport Tooltip from './Tooltip';\n\nexport interface MarkerWrapperProps extends React.HTMLAttributes<HTMLDivElement> {\n latitude: number;\n longitude: number;\n areaId?: string;\n areaValue?: number;\n additionalFields?: TooltipProps['additionalFields'];\n map: React.MutableRefObject<Map>;\n isChoroplethTooltipOpen?: boolean;\n}\n\nconst MarkerWrapper = ({\n longitude,\n latitude,\n areaId,\n areaValue,\n additionalFields = [],\n map,\n isChoroplethTooltipOpen,\n children,\n ...otherProps\n}: MarkerWrapperProps): JSX.Element => {\n const container = React.useRef<HTMLDivElement>();\n const marker = React.useRef<Marker>();\n const [isTooltipOpen, setTooltipOpenStatus] = React.useState(false);\n\n const isChoroplethTooltip = React.useCallback(() => isChoroplethTooltipOpen !== undefined, [\n isChoroplethTooltipOpen,\n ]);\n\n const openTooltip = React.useCallback(() => setTooltipOpenStatus(true), []);\n const closeTooltip = React.useCallback(() => setTooltipOpenStatus(false), []);\n\n const cleanupMarker = React.useCallback(() => {\n if (marker.current) {\n marker.current.remove();\n marker.current = undefined;\n }\n }, []);\n\n React.useEffect(() => {\n try {\n if (marker.current) {\n marker.current.setLngLat([longitude, latitude]);\n } else {\n marker.current = new Marker({ element: container.current });\n marker.current.setLngLat([longitude, latitude]);\n marker.current.addTo(map.current);\n }\n } catch (error) {\n console.error(error);\n cleanupMarker();\n }\n }, [latitude, longitude, map]);\n\n React.useEffect(() => cleanupMarker, []);\n\n return (\n <div style={{ visibility: isChoroplethTooltip() ? 'hidden' : 'visible' }}>\n <div\n style={{ visibility: isChoroplethTooltip() ? 'hidden' : 'visible' }}\n ref={container}\n data-test=\"map-marker\"\n onMouseOver={openTooltip}\n onMouseLeave={closeTooltip}\n onFocus={openTooltip}\n onBlur={closeTooltip}\n {...otherProps}\n >\n {children}\n </div>\n\n <div>\n <Tooltip\n open={isChoroplethTooltip() ? isChoroplethTooltipOpen : isTooltipOpen}\n anchor={container.current}\n latitude={isChoroplethTooltip() ? null : latitude}\n longitude={isChoroplethTooltip() ? null : longitude}\n areaId={areaId}\n areaValue={areaValue}\n additionalFields={additionalFields}\n />\n </div>\n </div>\n );\n};\n\nexport default MarkerWrapper;\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport type { Map } from 'maplibre-gl';\nimport { sum } from 'lodash';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport {\n bakeBubbleData,\n BubbleLayerType,\n DEFAULT_SERIES_COLORS,\n DEFAULT_RESULT_LIMIT,\n DEFAULT_CLUSTER_COLOR,\n getStaticColors,\n matchBubbleSize,\n} from './MapUtils';\nimport MarkerWrapper from './MarkerWrapper';\nimport type { TooltipProps } from './Tooltip';\n\nexport const GEO_BOUND_PREFIX = '_geo_bounds_';\nexport const GEO_LAT_AND_LONG_FIELD = ['_geo_long_field', '_geo_lat_field'];\nexport interface PieSegmentProps {\n start: number;\n end: number;\n radius: number;\n color: string;\n themeColor: string;\n segmentMetadata?: { name: string; value: number; color: string };\n handleBubbleClick?: (e: Event, name: string, count: number) => void;\n}\n\nexport const PieSegment = React.memo(\n ({\n start,\n end,\n radius,\n color,\n themeColor,\n segmentMetadata,\n handleBubbleClick,\n }: PieSegmentProps): JSX.Element => {\n const { name, value } = segmentMetadata ?? {};\n const handleSegmentClick = React.useCallback(\n e => {\n handleBubbleClick(e, name, value);\n },\n [name, value, handleBubbleClick]\n );\n\n if (end - start === 1) {\n return (\n <circle\n onClick={handleSegmentClick}\n cx={radius}\n cy={radius}\n r={radius}\n fill={color}\n fillOpacity={0.5}\n strokeWidth={1.5}\n stroke={color}\n />\n );\n }\n const a0 = 2 * Math.PI * (start - 0.25);\n const a1 = 2 * Math.PI * (end - 0.25);\n const x0 = Math.cos(a0);\n const y0 = Math.sin(a0);\n const x1 = Math.cos(a1);\n const y1 = Math.sin(a1);\n const arc = end - start > 0.5 ? 1 : 0;\n\n return (\n <path\n onClick={handleSegmentClick}\n d={`M ${radius} ${radius} L ${radius + radius * x0} ${\n radius + radius * y0\n } A ${radius} ${radius} 0 ${arc} 1 ${radius + radius * x1} ${\n radius + radius * y1\n } L ${radius} ${radius} A 0 0 0 ${arc} 0 ${radius} ${radius}`}\n fill={color}\n fillOpacity={0.8}\n stroke={themeColor}\n strokeWidth={2}\n strokeOpacity={0.3}\n />\n );\n }\n);\n\nPieSegment.displayName = 'MapBubblePieSegment';\n\nconst StyledMarkerWrapper = styled(MarkerWrapper)`\n cursor: pointer;\n`;\n\nexport interface BubbleProps {\n originalValues: number[];\n valueRange: number[];\n colors: string[];\n themeColor: string;\n isPie: boolean;\n latitude: number;\n longitude: number;\n bubbleSize: Required<TooltipProps['additionalFields'][number] & { value: number }>[];\n additionalFields?: TooltipProps['additionalFields'];\n map: React.MutableRefObject<Map>;\n handleMapClick?: any;\n}\n\nexport const Bubble = React.memo(\n ({\n originalValues,\n valueRange,\n colors,\n themeColor,\n isPie,\n latitude,\n longitude,\n bubbleSize,\n additionalFields = [],\n map,\n handleMapClick,\n }: BubbleProps): JSX.Element => {\n const onBubbleClick = React.useCallback(\n (e, name, value) => {\n handleMapClick(e, name, value);\n e.stopPropagation();\n },\n [handleMapClick]\n );\n\n const bubble = React.useMemo(() => {\n const allZeros = originalValues.every(v => v === 0);\n if (allZeros || !originalValues.length) {\n return null;\n }\n // sanitize values\n const values = originalValues.map(v => (v > 0 ? v : 0));\n\n // compute offsets for pie segments\n const offsets = [];\n let total = 0;\n values.forEach(count => {\n offsets.push(total);\n total += count;\n });\n\n const radius = matchBubbleSize(valueRange, total);\n const width = radius * 2;\n return (\n <svg width={width} height={width} viewBox={`-3 -3 ${width + 6} ${width + 6}`}>\n {isPie ? (\n <circle\n cx={radius}\n cy={radius}\n r={radius}\n fill=\"none\"\n strokeWidth={2}\n stroke={themeColor}\n strokeOpacity={0.3}\n />\n ) : null}\n {values.map((v, i) => (\n <PieSegment\n key={String(i)}\n start={offsets[i] / total}\n end={(offsets[i] + v) / total}\n radius={radius}\n color={colors[i]}\n themeColor={themeColor}\n segmentMetadata={bubbleSize[i]}\n handleBubbleClick={onBubbleClick}\n />\n ))}\n </svg>\n );\n }, [bubbleSize, colors, isPie, onBubbleClick, originalValues, themeColor, valueRange]);\n\n if (!bubble) {\n return null;\n }\n\n return (\n <StyledMarkerWrapper\n longitude={longitude}\n latitude={latitude}\n additionalFields={[...bubbleSize, ...additionalFields]}\n map={map}\n data-test-type=\"bubble\"\n >\n {bubble}\n </StyledMarkerWrapper>\n );\n }\n);\nBubble.displayName = 'MapBubble';\n\nexport interface BubbleLayerProps {\n bubbleLayer: BubbleLayerType;\n themeColorScheme: string;\n zoom: number;\n map: React.MutableRefObject<Map>;\n onMapClick?: any;\n}\n\nconst BubbleLayer = (props: BubbleLayerProps): JSX.Element => {\n const { bubbleLayer, themeColorScheme, map, zoom, onMapClick } = props;\n bubbleLayer.seriesColors = bubbleLayer.seriesColors || DEFAULT_SERIES_COLORS;\n bubbleLayer.bubbleSize = bubbleLayer.bubbleSize || [];\n const bakedData = React.useMemo(() => bakeBubbleData(bubbleLayer), [bubbleLayer]);\n const staticColors = React.useMemo(\n () => getStaticColors(bubbleLayer.bubbleSize.length, bubbleLayer.seriesColors),\n [bubbleLayer.bubbleSize.length, bubbleLayer.seriesColors]\n );\n const { data = [], dataRange = [], resultLimit, bubbleSizeFields, isPie } = bakedData ?? {};\n const { additionalTooltipFields = [] } = bubbleLayer;\n const roundedZoom = Math.round(zoom);\n const themeColor = themeColorScheme === 'light' ? '#ffffff' : '#1a1c20';\n const dynamicColors = bubbleLayer.dataColors;\n\n // filter data for the current zoom level and sort base on values\n const dataToRender = React.useMemo(\n () =>\n data\n .reduce((acc, datum, i) => {\n if (datum.zoom === roundedZoom) {\n acc.push({ data: datum, idx: i });\n }\n return acc;\n }, [])\n .slice(0, resultLimit || DEFAULT_RESULT_LIMIT)\n .sort((a, b) => sum(b.data.values) - sum(a.data.values)),\n [data, resultLimit, roundedZoom]\n );\n\n const handleMapClick = React.useCallback(\n (e, name, value, i) => {\n // retrieve metadata from the appropriate datum, indexed by i\n const metadata = dataToRender[i]?.data?.metadata ?? {};\n const payload = Object.keys(metadata).reduce(\n (acc, curr) => {\n const key = `row.${curr}.value`;\n const val = String(metadata[curr]);\n return { ...acc, [key]: val };\n },\n { name, value: String(value) }\n );\n\n onMapClick({ e, payload });\n },\n [dataToRender, onMapClick]\n );\n\n return (\n <>\n {dataToRender.map((datum, i) => {\n const colors = dynamicColors\n ? [\n dataToRender.map(obj =>\n isColor(dynamicColors[obj.idx]) ? dynamicColors[obj.idx] : DEFAULT_CLUSTER_COLOR\n )[i],\n ]\n : staticColors;\n\n const [longitude, latitude] = datum.data.coordinates;\n const bubbleSize = datum.data.values.map((value, index) => ({\n name: bubbleSizeFields[index],\n value,\n color: colors[index],\n }));\n\n const additionalFields = bubbleLayer.metadata\n ? additionalTooltipFields.map(field => ({\n name: field,\n value: datum.data.metadata[field],\n }))\n : [];\n\n return (\n <Bubble\n key={String(i)}\n originalValues={datum.data.values}\n valueRange={dataRange}\n colors={colors}\n themeColor={themeColor}\n isPie={isPie}\n longitude={longitude}\n latitude={latitude}\n bubbleSize={bubbleSize}\n additionalFields={additionalFields}\n map={map}\n handleMapClick={(e, name, value) => handleMapClick(e, name, value, i)}\n />\n );\n })}\n </>\n );\n};\n\nexport default BubbleLayer;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { isNumber } from '@splunk/visualization-encoding/utils/types';\nimport { getFieldsFromDSL } from '@splunk/visualization-encoding/utils/dsl';\nimport { deepMergeWithArrayPrimitiveOverrides } from '@splunk/visualizations-shared/hocUtils';\nimport { pickFieldFromJSONSchema } from '@splunk/visualizations-shared/JSONSchemaUtils';\nimport { GEO_LAT_AND_LONG_FIELD } from '../../Map/PureMap/BubbleLayer';\n\nexport const columnsNullToZeros = (config, dataSources, options) => {\n const { primary } = dataSources;\n const { columns, fields } = primary.data;\n let newColumns = columns;\n const mergedOptions = deepMergeWithArrayPrimitiveOverrides(\n {},\n options,\n pickFieldFromJSONSchema(config.optionsSchema, 'default')\n );\n if (mergedOptions.layers?.[0]?.type === 'bubble') {\n const latitudeField = getFieldsFromDSL(mergedOptions.layers[0].latitude, dataSources)[0] || '';\n const longitudeField = getFieldsFromDSL(mergedOptions.layers[0].longitude, dataSources)[0] || '';\n const excludedFields = [latitudeField, longitudeField, 'geobin'].concat(GEO_LAT_AND_LONG_FIELD);\n const indicesToEvaluate = new Set(\n fields.reduce((arr, e, i) => {\n const field = typeof e === 'string' ? e : e.name.toString();\n if (!excludedFields.includes(field)) {\n arr.push(i);\n }\n return arr;\n }, [])\n );\n\n newColumns = columns.map((column, i) => {\n if (indicesToEvaluate.has(i)) {\n // sanitize value and convert string to numeric numbers\n return column.map(value => (!value || !isNumber(value) ? 0 : +value));\n }\n return column;\n });\n }\n\n const modifiedDatasources = {\n ...dataSources,\n primary: {\n ...primary,\n data: {\n ...primary.data,\n columns: newColumns,\n },\n },\n };\n\n return modifiedDatasources;\n};\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/utils/types\";\nexport * from \"@splunk/visualization-encoding/utils/types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/utils/dsl\";\nexport * from \"@splunk/visualization-encoding/utils/dsl\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/hocUtils\";\nexport * from \"@splunk/visualizations-shared/hocUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport * from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/colorUtils\";\nexport * from \"@splunk/visualizations-shared/colorUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"d3-scale\";\nexport * from \"d3-scale\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"chroma-js\";\nexport * from \"chroma-js\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-color-palettes\";\nexport * from \"@splunk/visualization-color-palettes\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-schemas\";\nexport * from \"@splunk/visualization-schemas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { forEach, sum, isNumber, min as lodashMin, max as lodashMax, get, isEqual, isObject } from 'lodash';\nimport { LngLatBoundsLike } from 'maplibre-gl';\nimport { scalePow } from 'd3-scale';\nimport chroma from 'chroma-js';\nimport type { MapContextInterface, BaseTileConfig } from '@splunk/visualization-context/MapContext';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport { VIZ_CATEGORICAL } from '@splunk/visualization-color-palettes';\nimport { isNumber as isNumberUtil } from '@splunk/visualization-encoding/utils/types';\nimport type { GeoJsonDataType } from '@splunk/visualizations-shared/mapUtils';\nimport { LAYER_TYPE } from '@splunk/visualization-schemas';\n\nexport const MAX_LATITUDE = 90;\nexport const MIN_LATITUDE = -90;\nexport const MAX_LONGITUDE = 180;\nexport const MIN_LONGITUDE = -180;\nexport const DEFAULT_RESULT_LIMIT = 1000;\nexport const DEFAULT_CLUSTER_COLOR = '#909090';\nexport const DEFAULT_SERIES_COLORS = VIZ_CATEGORICAL;\n// MapLibre requires a map style specification number which is always 8\nexport const MAP_STYLE_VERSION_NUMBER = 8;\n// currently using one [min, max] value set for bubbles across all zoom levels\n// TODO: design choices on [min, max] bubble size for different zoom levels\nexport const MIN_BUBBLE_RADIUS = 7.11; // 10px\nexport const MAX_BUBBLE_RADIUS = 45.26; // 85px\nexport const DEFAULT_OPACITY = 0.8;\nconst LONGITUDE = 'longitude';\nconst LATITUDE = 'latitude';\ninterface GenericLayerType {\n type: string;\n latitude: number[];\n longitude: number[];\n dataColors?: string[] | '';\n seriesColors: string[];\n additionalTooltipFields?: string[];\n resultLimit: number;\n metadata?: Array<{ [key: string]: number | string }>;\n}\n\nexport interface MarkerLayerType extends GenericLayerType {\n type: LAYER_TYPE.Marker;\n}\n\nexport interface BubbleLayerType extends GenericLayerType {\n type: LAYER_TYPE.Bubble;\n bubbleSize?: number[][] | number[];\n bubbleSizeFields: string[];\n dataValuesField?: string;\n geobin?: string[];\n}\n\ninterface BubbleLayerDatumType {\n zoom: number;\n values: number[];\n sanitizedValues: number[];\n coordinates: number[];\n}\n\nexport interface BubbleLayerDataType {\n data: BubbleLayerDatumType[];\n dataRange: number[];\n isPie: boolean;\n resultLimit: number;\n bubbleSizeFields: string[];\n}\n\nexport interface ChoroplethLayerType {\n type: LAYER_TYPE.Choropleth;\n areaIds: string[];\n areaValues: number[];\n dataColors: string[];\n additionalTooltipFields?: string[];\n geom?: GeoJsonDataType[];\n resultLimit?: number;\n metadata?: Array<{ [key: string]: number | string | GeoJsonDataType }>;\n source?: string;\n width?: string | number;\n height?: string | number;\n choroplethEmptyAreaColor?: string;\n choroplethStrokeColor?: string;\n choroplethOpacity?: number;\n}\n\n// todo(@ssahnoune) - look into this\nexport interface MapLayerClickPayloadType {\n name?: string;\n value?: string | number;\n /* cell values of all cells of clicked row with the field and value - in shape row.<field>.value */\n [key: string]: string | number;\n}\n\nexport type ClusterLayerType = BubbleLayerType | MarkerLayerType;\nexport type LayerType = ClusterLayerType | ChoroplethLayerType;\n/**\n * Construct a tile preset {key: config} by combining the default + custom tile configs\n * Also returns the default tile config for each theme - light/dark\n * @param {MapContextInterface} args\n * @param {BaseTileConfig[]} args.defaultTileConfig\n * @param {BaseTileConfig[]} args.customTileConfig\n * @returns {Object} tile preset\n */\nexport const getTilePreset = ({\n defaultTileConfig = [],\n customTileConfig = [],\n}: MapContextInterface): {\n tilePreset: Record<string, BaseTileConfig>;\n defaultTileLight: BaseTileConfig;\n defaultTileDark: BaseTileConfig;\n} => {\n const tilePreset = {};\n let defaultTileLight = {};\n let defaultTileDark = {};\n const tileConfigs = [].concat(defaultTileConfig).concat(customTileConfig);\n forEach(tileConfigs, tileConfig => {\n const key = tileConfig?.key;\n const updatedConfig = { theme: 'all', ...tileConfig, version: MAP_STYLE_VERSION_NUMBER };\n tilePreset[key] = updatedConfig;\n });\n\n if (defaultTileConfig.length > 0) {\n defaultTileLight =\n defaultTileConfig.find(config => config.theme === 'light') ??\n defaultTileConfig.find(config => config.theme === undefined);\n defaultTileDark =\n defaultTileConfig.find(config => config.theme === 'dark') ??\n defaultTileConfig.find(config => config.theme === undefined);\n }\n\n return { tilePreset, defaultTileLight, defaultTileDark };\n};\n\n/**\n * Check if baseLayerTileServer is in tilePreset and config matches current theme, if yes, return.\n * If no, construct a mapStyle with baseLayerTilerServer and baseLayerTileServerType\n * Else return default tile config based on current theme\n * @param {Object} args\n * @param {BaseTileConfig[]} args.tilePreset\n * @param {String} args.baseLayerTilerServer\n * @param {String} args.baseLayerTileServerType\n * @param {String} args.colorScheme\n * @param {BaseTileConfig} args.defaultTileDark\n * @param {BaseTileConfig} args.defaultTileLight\n * @returns {BaseTileConfig} mapStyle\n */\nexport const getMapStyle = ({\n showBaseLayer,\n baseLayerTileServer = '',\n baseLayerTileServerType = '',\n tilePreset = {},\n colorScheme = 'light',\n defaultTileLight = {},\n defaultTileDark = {},\n}: {\n showBaseLayer: boolean;\n baseLayerTileServer?: string;\n baseLayerTileServerType?: string;\n tilePreset?: Record<string, BaseTileConfig>;\n colorScheme?: string;\n defaultTileLight?: BaseTileConfig;\n defaultTileDark?: BaseTileConfig;\n}): BaseTileConfig => {\n if (!showBaseLayer) {\n return {\n version: MAP_STYLE_VERSION_NUMBER,\n sources: {\n 'base-tiles': {\n type: 'raster',\n tiles: [\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',\n ],\n tileSize: 256,\n },\n },\n layers: [\n {\n id: 'base-layer',\n type: 'raster',\n source: 'base-tiles',\n minzoom: 0,\n maxzoom: 22,\n },\n ],\n };\n }\n\n if (\n baseLayerTileServer &&\n tilePreset[baseLayerTileServer] &&\n (tilePreset[baseLayerTileServer].theme === colorScheme ||\n tilePreset[baseLayerTileServer].theme === 'all')\n ) {\n return tilePreset[baseLayerTileServer];\n }\n\n if (baseLayerTileServer && baseLayerTileServerType) {\n let tiles = [];\n /**\n * Tile Server URLs (eg: http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png) can specify the variable {s} which refers to a subdomain\n * Subdomains are used to help with browser parallel requests per domain limitation. These subdomains are typically single letters 'a', 'b' and 'c'\n * Refer to https://leafletjs.com/SlavaUkraini/reference.html#tilelayer and https://wiki.openstreetmap.org/wiki/Tile_servers\n */\n if (baseLayerTileServer.match(/^(https?):\\/\\/{(s|S)}\\../)) {\n /**\n * sXML (Leaflet) allows users to define their own tile server URLs + list of available subdomains\n * In order to preserve this behavior during conversion to splunk.map,\n * if the variable {s} or {S} is detected, replace it with 'a', 'b' and 'c' - default values for subdomains\n * TODO: in the future, add an additional prop - baseLayerTileServerSubdomains: ['x', 'y', 'z'], default being ['a', 'b', 'c']\n */\n tiles = [\n baseLayerTileServer.replace(/{(s|S)}/, 'a'),\n baseLayerTileServer.replace(/{(s|S)}/, 'b'),\n baseLayerTileServer.replace(/{(s|S)}/, 'c'),\n ];\n } else {\n tiles = [baseLayerTileServer];\n }\n // TODO: remove hardcoded style when we allow users to pass in layer style through Viz options\n const mapStyle = {\n version: MAP_STYLE_VERSION_NUMBER,\n sources: {\n 'base-tiles': {\n type: baseLayerTileServerType,\n tiles,\n tileSize: 256,\n },\n },\n layers: [\n {\n id: 'base-layer',\n type: 'raster',\n source: 'base-tiles',\n minzoom: 0,\n maxzoom: 24, // https://maplibre.org/maplibre-gl-js-docs/api/map/\n },\n ],\n };\n return mapStyle;\n }\n\n // if tile server is not present in the preset AND we can't construct a mapStyle, fall back on defaults\n return colorScheme === 'light' ? defaultTileLight : defaultTileDark;\n};\n\nexport interface ZoomConstraints {\n minZoom: number;\n maxZoom: number;\n}\n\nexport const getZoomConstraintsFromTileConfig = (\n tileConfig: BaseTileConfig,\n baseLayerTileServer?: string\n): ZoomConstraints => {\n const { sources, layers } = tileConfig;\n let matchedBaseLayerTileServer = false;\n // check sources for minzoom maxzoom first\n const sourceKeys = Object.keys(sources);\n for (let i = 0; i < sourceKeys.length; i += 1) {\n const { minzoom, maxzoom } = sources[sourceKeys[i]];\n if (baseLayerTileServer && sources[sourceKeys[i]].tiles.indexOf(baseLayerTileServer) !== -1) {\n matchedBaseLayerTileServer = true;\n }\n if (\n ((baseLayerTileServer && matchedBaseLayerTileServer) || !baseLayerTileServer) &&\n isNumber(minzoom) &&\n isNumber(maxzoom)\n ) {\n return {\n minZoom: minzoom,\n maxZoom: maxzoom,\n };\n }\n }\n // then check layers\n for (let i = 0; i < layers.length; i += 1) {\n const { minzoom, maxzoom } = layers[i];\n if (\n ((baseLayerTileServer && matchedBaseLayerTileServer) || !baseLayerTileServer) &&\n isNumber(minzoom) &&\n isNumber(maxzoom)\n ) {\n return {\n minZoom: minzoom,\n maxZoom: maxzoom,\n };\n }\n }\n // Maplibre default - would reset previous min/maxZoom https://maplibre.org/maplibre-gl-js-docs/api/map/\n return {\n minZoom: 0,\n maxZoom: 24,\n };\n};\n\nexport const getZoomLevelFromGeobin = (geobinStr: string): number => {\n if (!geobinStr) {\n return null;\n }\n // geostats cmds return geobin with zoom level 0-18, 0-99 in the geobinPattern covers the range\n const geobinPattern = /bin_id_zl_([0-9]{0,2})?_y_/g;\n const match = geobinPattern.exec(geobinStr);\n return (match?.length && parseInt(match[1], 10)) ?? null;\n};\n\n// Bubble colors - static\nexport const getStaticColors = (colorCount: number, colorArray: string[]): string[] => {\n if (colorCount < 0 || !colorCount) {\n return [DEFAULT_CLUSTER_COLOR];\n }\n if (!colorArray || !colorArray.length) {\n return [...Array(colorCount).keys()].map(i => DEFAULT_SERIES_COLORS[i]);\n }\n // loop through colorArray to pick the first $colorCount colors\n // start from begining again if colorCount > colorArray.length\n return [...Array(colorCount).keys()].map(i =>\n isColor(colorArray[i % colorArray.length]) ? colorArray[i % colorArray.length] : DEFAULT_CLUSTER_COLOR\n );\n};\n\n// Bubble size\nexport const matchBubbleSize = (dataRange: number[], data: number): any => {\n const size = scalePow().exponent(0.2).domain(dataRange).range([MIN_BUBBLE_RADIUS, MAX_BUBBLE_RADIUS])(\n data\n );\n\n if (size > MAX_BUBBLE_RADIUS) {\n return MAX_BUBBLE_RADIUS;\n }\n if (size < MIN_BUBBLE_RADIUS) {\n return MIN_BUBBLE_RADIUS;\n }\n return size;\n};\n\nexport const transposeArray = (array: number[][]): number[][] => {\n if (!array || !array.length || !array[0] || !array[0].length) {\n return [];\n }\n return array[0].map((_, i) => array.map(row => row[i]));\n};\n\n// sanitize values: update all null, undefined, or negative values to 0\nexport const sanitizeValues = (values: number[] | number[][]) => {\n // null / undefined\n if (!values) {\n return 0;\n }\n // number\n if (!Array.isArray(values)) {\n return values > 0 ? values : 0;\n }\n // array\n return values.map(arr => sanitizeValues(arr));\n};\n\n// eslint-disable-next-line consistent-return\nexport const sortByValuesField = (bubbleLayer: BubbleLayerType) => {\n const { bubbleSizeFields, dataValuesField } = bubbleLayer;\n\n // Find the index of dataValuesField in fields\n const index = bubbleSizeFields.indexOf(dataValuesField);\n if (index === -1) return bubbleLayer; // If not found, return as is\n\n // Move dataValuesField and corresponding sizes to the first position\n bubbleLayer.bubbleSizeFields.unshift(bubbleLayer.bubbleSizeFields.splice(index, 1)[0]);\n bubbleLayer.bubbleSize.unshift(bubbleLayer.bubbleSize.splice(index, 1)[0] as number & number[]);\n};\n\nexport const bakeBubbleData = (layer: BubbleLayerType): BubbleLayerDataType => {\n if (\n !layer ||\n !layer.bubbleSize?.length ||\n !layer.geobin ||\n !layer.geobin.length ||\n !layer.latitude ||\n !layer.latitude.length ||\n !layer.longitude ||\n !layer.longitude.length\n ) {\n return null;\n }\n // if bubbleSize is passed as an array of single number array (data series)\n // e.g. [value0, value1, ...]\n // format each value as an array to unify data operations for data series and frames\n const sanitizedBubbleSize = sanitizeValues(layer.bubbleSize);\n let transposedBubbleSize: number[][];\n let transposedSanitizedBubbleSize: number[][];\n let isPie = false;\n // format array if bubbleSize is passed as an array of array (data frame)\n if (Array.isArray(layer.bubbleSize[0])) {\n // one-time array transpose,\n // e.g. from [column0data, column0data] (multi series)\n // to [[column0datum0, column1datum0], [column0datum1, column1data1], ...]\n // or e.g. from [column0data] (single series)\n // to [[column0data]]\n // for easy access of values at each geo location,\n // and min max pie size computation\n transposedBubbleSize = transposeArray(layer.bubbleSize as number[][]);\n transposedSanitizedBubbleSize = transposeArray(sanitizedBubbleSize);\n // if multiple series in the dataframe, set isPie to true\n if (layer.bubbleSize.length > 1) {\n isPie = true;\n // when dynamic coloring is enabled,\n // set the configured dataValues field as the first field\n // to apply dynamic colors only to the first pie slice.\n if (layer.dataValuesField && !!layer.dataColors) {\n sortByValuesField(layer);\n }\n }\n } else {\n transposedBubbleSize = layer.bubbleSize.map(n => [n]);\n transposedSanitizedBubbleSize = sanitizedBubbleSize.map(n => [n]);\n }\n if (!transposedBubbleSize || !transposedBubbleSize.length) {\n return null;\n }\n const data = layer.latitude\n .map((lat, i) => ({\n zoom: getZoomLevelFromGeobin(layer.geobin[i]),\n values: transposedBubbleSize[i],\n sanitizedValues: transposedSanitizedBubbleSize[i],\n coordinates: [layer.longitude[i], lat],\n metadata: layer.metadata ? layer.metadata[i] : {},\n }))\n .filter(d => Boolean(d.values));\n\n // compute the min/max value to encode min/max pie or bubble size\n let min = sum(transposedSanitizedBubbleSize[0]);\n let max = sum(transposedSanitizedBubbleSize[1]);\n transposedSanitizedBubbleSize.forEach(row => {\n const bubbleSize = sum(row);\n max = bubbleSize > max ? bubbleSize : max;\n min = bubbleSize < min ? bubbleSize : min;\n });\n return {\n data,\n dataRange: [min, max],\n isPie,\n resultLimit: layer.resultLimit,\n bubbleSizeFields: layer.bubbleSizeFields,\n };\n};\n\nexport const isValidLatLon = (latlon: Array<number | string>): boolean => {\n if (!latlon || !Array.isArray(latlon) || latlon.length !== 2) {\n return false;\n }\n const [lat, lon] = latlon;\n if (!isNumberUtil(lat) || !(Number(lat) >= MIN_LATITUDE && Number(lat) <= MAX_LATITUDE)) {\n return false;\n }\n if (!isNumberUtil(lon) || !(Number(lon) >= MIN_LONGITUDE && Number(lon) <= MAX_LONGITUDE)) {\n return false;\n }\n return true;\n};\n\n/**\n * Returns a list of all lat or lon coordinates used in a specified layer\n * @param {LayerType[]} layer\n * @param {string} field\n * @returns {number[]} list of lat coordinates or lon coordinates\n */\nconst getLatOrLonCoordinates = (layer: LayerType, field: string): number[] => {\n const getClusterValues = (clusterLayer: ClusterLayerType): number[] =>\n get(clusterLayer, field, []).slice(\n 0,\n clusterLayer.type === LAYER_TYPE.Marker && clusterLayer.resultLimit\n ? clusterLayer.resultLimit\n : DEFAULT_RESULT_LIMIT\n );\n\n const getChoroplethValues = (choroplethLayer: ChoroplethLayerType): number[] => {\n const slicedGeomList = choroplethLayer.geom.slice(0, choroplethLayer.resultLimit);\n const flatCoordinates = slicedGeomList.flatMap(geomObject => geomObject.coordinates.flat(2));\n return flatCoordinates.map(coord => coord[field === LONGITUDE ? 0 : 1]);\n };\n\n return layer.type === LAYER_TYPE.Choropleth\n ? getChoroplethValues(layer as ChoroplethLayerType)\n : getClusterValues(layer as ClusterLayerType);\n};\n\n/**\n * Returns the min and max LongLat pairs to determine the layer boundaries to fit all markers/bubbles\n * @param {LayerType[]} layers\n * @returns {LngLatBoundsLike}\n */\nexport const getGlobalLayerBoundaries = (layers: LayerType[]): LngLatBoundsLike => {\n const isLayerValid = (field: string): boolean =>\n layers.every(layer => layer[field] || (layer as ChoroplethLayerType).geom);\n const getDefaultMax = (field: string) => (field === LONGITUDE ? MAX_LONGITUDE : MAX_LATITUDE);\n const getDefaultMin = (field: string) => (field === LONGITUDE ? MIN_LONGITUDE : MIN_LATITUDE);\n\n if (!layers || !Array.isArray(layers) || !layers.length) {\n return null;\n }\n\n const getMin = (field: string): number => {\n if (!isLayerValid(field)) {\n return getDefaultMin(field);\n }\n return layers.reduce((prevVal, layer) => {\n const coordinatesNumArr = getLatOrLonCoordinates(layer, field).map(x => +x);\n return lodashMin([prevVal, ...coordinatesNumArr]);\n }, getDefaultMax(field));\n };\n\n const getMax = (field: string): number => {\n if (!isLayerValid(field)) {\n return getDefaultMax(field);\n }\n return layers.reduce((prevVal, layer) => {\n const coordinatesNumArr = getLatOrLonCoordinates(layer, field).map(Number);\n return lodashMax([prevVal, ...coordinatesNumArr]);\n }, getDefaultMin(field));\n };\n\n return [\n [getMin(LONGITUDE), getMin(LATITUDE)],\n [getMax(LONGITUDE), getMax(LATITUDE)],\n ];\n};\n\nexport const getScaledOpacities = (colors: string[], cfgOpacity: number): number[] => {\n // extract opacity information from 8 digit hex codes\n const opacities = colors?.map(color => (color?.length === 9 ? chroma(color).alpha() ?? 1 : 1));\n // opacity cannot be greater than configured opacity\n return opacities?.map(opacity => opacity * cfgOpacity);\n};\n\nexport const compareBaseStyles = (curr, next): boolean => {\n const currBaseLayer = curr?.layers?.find(layer => layer?.id === 'base-layer');\n const nextBaseLayer = next?.layers?.find(layer => layer?.id === 'base-layer');\n const currBaseSource = get(curr?.sources, (currBaseLayer?.source as string) ?? '');\n const nextBaseSource = get(next?.sources, (nextBaseLayer?.source as string) ?? '');\n\n if (!currBaseLayer || !nextBaseLayer || !currBaseSource || !nextBaseSource) {\n return false;\n }\n\n return isEqual(currBaseLayer, nextBaseLayer) && isEqual(currBaseSource, nextBaseSource);\n};\n\nexport const formatMetadata = (\n choroplethLayer: ChoroplethLayerType,\n i: number\n): { [key: string]: string } => {\n if (!choroplethLayer || !choroplethLayer.areaIds || !choroplethLayer.areaValues) return {};\n if (i >= choroplethLayer.areaIds.length) return {};\n\n const metadata = choroplethLayer.metadata ? choroplethLayer.metadata[i] : {};\n const name = choroplethLayer.areaIds[i];\n const value = choroplethLayer.areaValues[i];\n const base = { name, value: String(value) };\n\n return Object.keys(metadata).reduce((result, curr) => {\n const key = `row.${curr}.value`;\n const val = isObject(metadata[curr]) ? JSON.stringify(metadata[curr]) : String(metadata[curr]);\n return { ...result, [key]: val };\n }, base);\n};\n", "\nimport * as defaultImport from \"maplibre-gl\";\nexport * from \"maplibre-gl\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Popover\";\nexport * from \"@splunk/react-ui/Popover\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport Popover from '@splunk/react-ui/Popover';\nimport { _ } from '@splunk/ui-utils/i18n';\n\nconst StyledPopover = styled(Popover)`\n width: 250px;\n font-size: 12px;\n`;\n\nconst StyledTable = styled.table`\n margin: 2px 6px 2px 6px;\n width: calc(100% - 12px);\n`;\n\nconst StyledTitleColumn = styled.td`\n opacity: 0.85;\n`;\n\nconst StyledValueColumn = styled.td`\n text-align: right;\n`;\n\nconst StyledColorBlock = styled.div`\n background-color: ${props => props.color};\n display: inline-block;\n margin-right: 4px;\n border-radius: 2px;\n width: 6px;\n height: 11px;\n transform: translateY(1px);\n`;\n\nexport const convertDegToDMS = (decimalDegree: number, type: 'latitude' | 'longitude'): string => {\n const truncate = n => (n > 0 ? Math.floor(n) : Math.ceil(n));\n const absoluteDegree = Math.abs(decimalDegree);\n let degrees = truncate(absoluteDegree);\n let minutes = truncate((absoluteDegree - degrees) * 60);\n let seconds = Math.round((absoluteDegree - degrees - minutes / 60) * 3600);\n if (seconds === 60) {\n minutes += 1;\n seconds = 0;\n }\n if (minutes === 60) {\n degrees += 1;\n minutes = 0;\n }\n let direction: string;\n if (type === 'longitude') {\n direction = decimalDegree < 0 ? 'W' : 'E';\n } else if (type === 'latitude') {\n direction = decimalDegree < 0 ? 'S' : 'N';\n }\n return `${degrees}\u00B0 ${minutes}' ${seconds}\" ${direction}`;\n};\n\nexport interface TooltipProps {\n open?: boolean;\n anchor?: HTMLElement;\n latitude?: number;\n longitude?: number;\n areaId?: string;\n areaValue?: number;\n additionalFields?: Array<{ name: string; value: number | string; color?: string }>;\n}\n// only want latitude/longitude for marker and bubble\n// omit for choropleth, and put areaid, areavalue instead\nconst Tooltip = ({\n open,\n anchor,\n latitude,\n longitude,\n areaId,\n areaValue,\n additionalFields = [],\n}: TooltipProps): JSX.Element => (\n <StyledPopover\n open={open}\n animation={false}\n anchor={anchor}\n data-test=\"map-marker-tooltip\"\n defaultPlacement=\"above\"\n >\n <StyledTable>\n <tbody>\n {areaId && areaValue && (\n <tr>\n <StyledTitleColumn data-test=\"area-id\">{areaId}</StyledTitleColumn>\n <StyledValueColumn data-test=\"area-value\">{areaValue}</StyledValueColumn>\n </tr>\n )}\n {latitude && (\n <tr>\n <StyledTitleColumn>{_('Latitude')}</StyledTitleColumn>\n <StyledValueColumn data-test=\"latitude\">\n {convertDegToDMS(latitude, 'latitude')}\n </StyledValueColumn>\n </tr>\n )}\n {longitude && (\n <tr>\n <StyledTitleColumn>{_('Longitude')}</StyledTitleColumn>\n <StyledValueColumn data-test=\"longitude\">\n {convertDegToDMS(longitude, 'longitude')}\n </StyledValueColumn>\n </tr>\n )}\n {additionalFields\n .filter(({ value }) => value && String(value) !== '0')\n .map(({ name, value, color }, index) => (\n <tr key={String(index)}>\n <StyledTitleColumn data-test=\"field-title\">\n {color ? <StyledColorBlock data-test=\"field-color\" color={color} /> : null}\n {name}\n </StyledTitleColumn>\n <StyledValueColumn data-test=\"field-value\">{value}</StyledValueColumn>\n </tr>\n ))}\n </tbody>\n </StyledTable>\n </StyledPopover>\n);\n\nexport default Tooltip;\n", "import type { Map } from 'maplibre-gl';\nimport { Marker } from 'maplibre-gl';\nimport * as React from 'react';\nimport type { TooltipProps } from './Tooltip';\nimport Tooltip from './Tooltip';\n\nexport interface MarkerWrapperProps extends React.HTMLAttributes<HTMLDivElement> {\n latitude: number;\n longitude: number;\n areaId?: string;\n areaValue?: number;\n additionalFields?: TooltipProps['additionalFields'];\n map: React.MutableRefObject<Map>;\n isChoroplethTooltipOpen?: boolean;\n}\n\nconst MarkerWrapper = ({\n longitude,\n latitude,\n areaId,\n areaValue,\n additionalFields = [],\n map,\n isChoroplethTooltipOpen,\n children,\n ...otherProps\n}: MarkerWrapperProps): JSX.Element => {\n const container = React.useRef<HTMLDivElement>();\n const marker = React.useRef<Marker>();\n const [isTooltipOpen, setTooltipOpenStatus] = React.useState(false);\n\n const isChoroplethTooltip = React.useCallback(() => isChoroplethTooltipOpen !== undefined, [\n isChoroplethTooltipOpen,\n ]);\n\n const openTooltip = React.useCallback(() => setTooltipOpenStatus(true), []);\n const closeTooltip = React.useCallback(() => setTooltipOpenStatus(false), []);\n\n const cleanupMarker = React.useCallback(() => {\n if (marker.current) {\n marker.current.remove();\n marker.current = undefined;\n }\n }, []);\n\n React.useEffect(() => {\n try {\n if (marker.current) {\n marker.current.setLngLat([longitude, latitude]);\n } else {\n marker.current = new Marker({ element: container.current });\n marker.current.setLngLat([longitude, latitude]);\n marker.current.addTo(map.current);\n }\n } catch (error) {\n console.error(error);\n cleanupMarker();\n }\n }, [latitude, longitude, map]);\n\n React.useEffect(() => cleanupMarker, []);\n\n return (\n <div style={{ visibility: isChoroplethTooltip() ? 'hidden' : 'visible' }}>\n <div\n style={{ visibility: isChoroplethTooltip() ? 'hidden' : 'visible' }}\n ref={container}\n data-test=\"map-marker\"\n onMouseOver={openTooltip}\n onMouseLeave={closeTooltip}\n onFocus={openTooltip}\n onBlur={closeTooltip}\n {...otherProps}\n >\n {children}\n </div>\n\n <div>\n <Tooltip\n open={isChoroplethTooltip() ? isChoroplethTooltipOpen : isTooltipOpen}\n anchor={container.current}\n latitude={isChoroplethTooltip() ? null : latitude}\n longitude={isChoroplethTooltip() ? null : longitude}\n areaId={areaId}\n areaValue={areaValue}\n additionalFields={additionalFields}\n />\n </div>\n </div>\n );\n};\n\nexport default MarkerWrapper;\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport type { Map } from 'maplibre-gl';\nimport { sum } from 'lodash';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport {\n bakeBubbleData,\n BubbleLayerType,\n DEFAULT_SERIES_COLORS,\n DEFAULT_RESULT_LIMIT,\n DEFAULT_CLUSTER_COLOR,\n getStaticColors,\n matchBubbleSize,\n} from './MapUtils';\nimport MarkerWrapper from './MarkerWrapper';\nimport type { TooltipProps } from './Tooltip';\n\nexport const GEO_BOUND_PREFIX = '_geo_bounds_';\nexport const GEO_LAT_AND_LONG_FIELD = ['_geo_long_field', '_geo_lat_field'];\nexport interface PieSegmentProps {\n start: number;\n end: number;\n radius: number;\n color: string;\n themeColor: string;\n segmentMetadata?: { name: string; value: number; color: string };\n handleBubbleClick?: (e: Event, name: string, count: number) => void;\n}\n\nexport const PieSegment = React.memo(\n ({\n start,\n end,\n radius,\n color,\n themeColor,\n segmentMetadata,\n handleBubbleClick,\n }: PieSegmentProps): JSX.Element => {\n const { name, value } = segmentMetadata ?? {};\n const handleSegmentClick = React.useCallback(\n e => {\n handleBubbleClick(e, name, value);\n },\n [name, value, handleBubbleClick]\n );\n\n if (end - start === 1) {\n return (\n <circle\n onClick={handleSegmentClick}\n cx={radius}\n cy={radius}\n r={radius}\n fill={color}\n fillOpacity={0.5}\n strokeWidth={1.5}\n stroke={color}\n />\n );\n }\n const a0 = 2 * Math.PI * (start - 0.25);\n const a1 = 2 * Math.PI * (end - 0.25);\n const x0 = Math.cos(a0);\n const y0 = Math.sin(a0);\n const x1 = Math.cos(a1);\n const y1 = Math.sin(a1);\n const arc = end - start > 0.5 ? 1 : 0;\n\n return (\n <path\n onClick={handleSegmentClick}\n d={`M ${radius} ${radius} L ${radius + radius * x0} ${\n radius + radius * y0\n } A ${radius} ${radius} 0 ${arc} 1 ${radius + radius * x1} ${\n radius + radius * y1\n } L ${radius} ${radius} A 0 0 0 ${arc} 0 ${radius} ${radius}`}\n fill={color}\n fillOpacity={0.8}\n stroke={themeColor}\n strokeWidth={2}\n strokeOpacity={0.3}\n />\n );\n }\n);\n\nPieSegment.displayName = 'MapBubblePieSegment';\n\nconst StyledMarkerWrapper = styled(MarkerWrapper)`\n cursor: pointer;\n`;\n\nexport interface BubbleProps {\n originalValues: number[];\n valueRange: number[];\n colors: string[];\n themeColor: string;\n isPie: boolean;\n latitude: number;\n longitude: number;\n bubbleSize: Required<TooltipProps['additionalFields'][number] & { value: number }>[];\n additionalFields?: TooltipProps['additionalFields'];\n map: React.MutableRefObject<Map>;\n handleMapClick?: any;\n}\n\nexport const Bubble = React.memo(\n ({\n originalValues,\n valueRange,\n colors,\n themeColor,\n isPie,\n latitude,\n longitude,\n bubbleSize,\n additionalFields = [],\n map,\n handleMapClick,\n }: BubbleProps): JSX.Element => {\n const onBubbleClick = React.useCallback(\n (e, name, value) => {\n handleMapClick(e, name, value);\n e.stopPropagation();\n },\n [handleMapClick]\n );\n\n const bubble = React.useMemo(() => {\n const allZeros = originalValues.every(v => v === 0);\n if (allZeros || !originalValues.length) {\n return null;\n }\n // sanitize values\n const values = originalValues.map(v => (v > 0 ? v : 0));\n\n // compute offsets for pie segments\n const offsets = [];\n let total = 0;\n values.forEach(count => {\n offsets.push(total);\n total += count;\n });\n\n const radius = matchBubbleSize(valueRange, total);\n const width = radius * 2;\n return (\n <svg width={width} height={width} viewBox={`-3 -3 ${width + 6} ${width + 6}`}>\n {isPie ? (\n <circle\n cx={radius}\n cy={radius}\n r={radius}\n fill=\"none\"\n strokeWidth={2}\n stroke={themeColor}\n strokeOpacity={0.3}\n />\n ) : null}\n {values.map((v, i) => (\n <PieSegment\n key={String(i)}\n start={offsets[i] / total}\n end={(offsets[i] + v) / total}\n radius={radius}\n color={colors[i]}\n themeColor={themeColor}\n segmentMetadata={bubbleSize[i]}\n handleBubbleClick={onBubbleClick}\n />\n ))}\n </svg>\n );\n }, [bubbleSize, colors, isPie, onBubbleClick, originalValues, themeColor, valueRange]);\n\n if (!bubble) {\n return null;\n }\n\n return (\n <StyledMarkerWrapper\n longitude={longitude}\n latitude={latitude}\n additionalFields={[...bubbleSize, ...additionalFields]}\n map={map}\n data-test-type=\"bubble\"\n >\n {bubble}\n </StyledMarkerWrapper>\n );\n }\n);\nBubble.displayName = 'MapBubble';\n\nexport interface BubbleLayerProps {\n bubbleLayer: BubbleLayerType;\n themeColorScheme: string;\n zoom: number;\n map: React.MutableRefObject<Map>;\n onMapClick?: any;\n}\n\nconst BubbleLayer = (props: BubbleLayerProps): JSX.Element => {\n const { bubbleLayer, themeColorScheme, map, zoom, onMapClick } = props;\n bubbleLayer.seriesColors = bubbleLayer.seriesColors || DEFAULT_SERIES_COLORS;\n bubbleLayer.bubbleSize = bubbleLayer.bubbleSize || [];\n const bakedData = React.useMemo(() => bakeBubbleData(bubbleLayer), [bubbleLayer]);\n const staticColors = React.useMemo(\n () => getStaticColors(bubbleLayer.bubbleSize.length, bubbleLayer.seriesColors),\n [bubbleLayer.bubbleSize.length, bubbleLayer.seriesColors]\n );\n const { data = [], dataRange = [], resultLimit, bubbleSizeFields, isPie } = bakedData ?? {};\n const { additionalTooltipFields = [] } = bubbleLayer;\n const roundedZoom = Math.round(zoom);\n const themeColor = themeColorScheme === 'light' ? '#ffffff' : '#1a1c20';\n const dynamicColors = bubbleLayer.dataColors;\n\n // filter data for the current zoom level and sort base on values\n const dataToRender = React.useMemo(\n () =>\n data\n .reduce((acc, datum, i) => {\n if (datum.zoom === roundedZoom) {\n acc.push({ data: datum, idx: i });\n }\n return acc;\n }, [])\n .slice(0, resultLimit || DEFAULT_RESULT_LIMIT)\n .sort((a, b) => sum(b.data.values) - sum(a.data.values)),\n [data, resultLimit, roundedZoom]\n );\n\n const handleMapClick = React.useCallback(\n (e, name, value, i) => {\n // retrieve metadata from the appropriate datum, indexed by i\n const metadata = dataToRender[i]?.data?.metadata ?? {};\n const payload = Object.keys(metadata).reduce(\n (acc, curr) => {\n const key = `row.${curr}.value`;\n const val = String(metadata[curr]);\n return { ...acc, [key]: val };\n },\n { name, value: String(value) }\n );\n\n onMapClick({ e, payload });\n },\n [dataToRender, onMapClick]\n );\n\n return (\n <>\n {dataToRender.map((datum, i) => {\n const colors = dynamicColors\n ? [\n dataToRender.map(obj =>\n isColor(dynamicColors[obj.idx]) ? dynamicColors[obj.idx] : DEFAULT_CLUSTER_COLOR\n )[i],\n ]\n : staticColors;\n\n const [longitude, latitude] = datum.data.coordinates;\n const bubbleSize = datum.data.values.map((value, index) => ({\n name: bubbleSizeFields[index],\n value,\n color: colors[index],\n }));\n\n const additionalFields = bubbleLayer.metadata\n ? additionalTooltipFields.map(field => ({\n name: field,\n value: datum.data.metadata[field],\n }))\n : [];\n\n return (\n <Bubble\n key={String(i)}\n originalValues={datum.data.values}\n valueRange={dataRange}\n colors={colors}\n themeColor={themeColor}\n isPie={isPie}\n longitude={longitude}\n latitude={latitude}\n bubbleSize={bubbleSize}\n additionalFields={additionalFields}\n map={map}\n handleMapClick={(e, name, value) => handleMapClick(e, name, value, i)}\n />\n );\n })}\n </>\n );\n};\n\nexport default BubbleLayer;\n"],
5
+ "mappings": "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",
6
6
  "names": ["defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport"]
7
7
  }
@@ -227,13 +227,13 @@ var computeText = ({
227
227
  return text;
228
228
  };
229
229
  var getMajorText = ({
230
- majorValue,
230
+ majorValueDisplay,
231
231
  numberPrecision,
232
232
  shouldUseThousandSeparators,
233
233
  shouldAbbreviateMajorValue
234
234
  }) => computeText({
235
- value: majorValue === null ? "N/A" : majorValue,
236
- // if majorValue is null, use `N/A`.
235
+ value: majorValueDisplay === null ? "N/A" : majorValueDisplay,
236
+ // if majorValueDisplay is null, use `N/A`.
237
237
  numberPrecision,
238
238
  shouldUseThousandSeparators,
239
239
  shouldAbbreviateValue: shouldAbbreviateMajorValue
@@ -308,6 +308,7 @@ var getMajorAndTrend = ({
308
308
  width,
309
309
  height,
310
310
  majorValue,
311
+ majorValueDisplay,
311
312
  trendValue,
312
313
  majorFontSize,
313
314
  trendFontSize,
@@ -322,7 +323,7 @@ var getMajorAndTrend = ({
322
323
  const textContentWidth = width * 0.9;
323
324
  const textContentHeight = height * 0.9;
324
325
  const majorText = getMajorText({
325
- majorValue,
326
+ majorValueDisplay,
326
327
  numberPrecision,
327
328
  shouldUseThousandSeparators,
328
329
  shouldAbbreviateMajorValue
@@ -360,6 +361,7 @@ var updateVizInSmallSpace = ({
360
361
  height,
361
362
  toRemoveList,
362
363
  majorValue,
364
+ majorValueDisplay,
363
365
  trendValue,
364
366
  majorFontSize,
365
367
  trendFontSize,
@@ -380,6 +382,7 @@ var updateVizInSmallSpace = ({
380
382
  });
381
383
  newMajorAndTrend = getMajorAndTrend(__spreadValues({
382
384
  majorValue,
385
+ majorValueDisplay,
383
386
  trendValue,
384
387
  majorFontSize,
385
388
  trendFontSize,
@@ -394,9 +397,10 @@ var updateVizInSmallSpace = ({
394
397
  removeIndex += 1;
395
398
  }
396
399
  if (newTextSize < 12) {
397
- const truncateValue = `${majorValue.toString().slice(0, 3)}...`;
400
+ const truncateValue = `${(majorValueDisplay || majorValue).toString().slice(0, 3)}...`;
398
401
  newMajorAndTrend = getMajorAndTrend(__spreadValues({
399
- majorValue: truncateValue,
402
+ majorValue,
403
+ majorValueDisplay: truncateValue,
400
404
  trendValue,
401
405
  majorFontSize,
402
406
  trendFontSize,
@@ -416,6 +420,7 @@ var computeSingleValueContent = ({
416
420
  containerWidth,
417
421
  containerHeight,
418
422
  majorValue,
423
+ majorValueDisplay,
419
424
  trendValue,
420
425
  majorFontSize,
421
426
  trendFontSize,
@@ -429,6 +434,7 @@ var computeSingleValueContent = ({
429
434
  }) => {
430
435
  let { majorText, trendText, majorTextFontSize, trendTextFontSize } = getMajorAndTrend({
431
436
  majorValue,
437
+ majorValueDisplay: majorValueDisplay || majorValue,
432
438
  trendValue,
433
439
  majorFontSize,
434
440
  trendFontSize,
@@ -449,6 +455,7 @@ var computeSingleValueContent = ({
449
455
  height: containerHeight,
450
456
  toRemoveList,
451
457
  majorValue,
458
+ majorValueDisplay: majorValueDisplay || majorValue,
452
459
  trendValue,
453
460
  majorFontSize,
454
461
  trendFontSize,
@@ -495,6 +502,7 @@ var computeSingleValueRadialContent = ({
495
502
  containerWidth,
496
503
  containerHeight,
497
504
  majorValue,
505
+ majorValueDisplay,
498
506
  trendValue,
499
507
  majorFontSize,
500
508
  trendFontSize,
@@ -508,6 +516,7 @@ var computeSingleValueRadialContent = ({
508
516
  }) => {
509
517
  let { majorText, trendText, majorTextFontSize, trendTextFontSize } = getMajorAndTrend({
510
518
  majorValue,
519
+ majorValueDisplay: majorValueDisplay || majorValue,
511
520
  trendValue,
512
521
  majorFontSize,
513
522
  trendFontSize,
@@ -524,13 +533,14 @@ var computeSingleValueRadialContent = ({
524
533
  let smallVizProps = {};
525
534
  if (smallViz) {
526
535
  const truncateValue = minimallyTruncateStringToWidth({
527
- text: majorValue,
536
+ text: majorValueDisplay || majorValue,
528
537
  fontWeight: "bold",
529
538
  fontSize: 12,
530
539
  containerWidth
531
540
  });
532
541
  ({ majorText, trendText, majorTextFontSize, trendTextFontSize } = getMajorAndTrend({
533
- majorValue: truncateValue,
542
+ majorValueDisplay: truncateValue,
543
+ majorValue,
534
544
  trendValue,
535
545
  majorFontSize,
536
546
  trendFontSize,