{"version":3,"file":"utils.cjs","sources":["../src/js/utils.ts"],"sourcesContent":["import { useContext } from 'react';\nimport { ThemeContext } from 'styled-components';\n\ndeclare module 'styled-components' {\n  export interface DefaultTheme {\n    icon?: {\n      disableScaleDown?: boolean;\n      size?: Record<string, string>;\n    };\n    text?: Record<string, { height: string }>;\n  }\n}\n\nexport function isObject(item: unknown): item is Record<string, unknown> {\n  return !!item && typeof item === 'object' && !Array.isArray(item);\n}\n\ntype ThemeObject = {\n  [key: string]: unknown;\n};\n\nexport const deepMerge = (\n  target: ThemeObject,\n  ...sources: Partial<ThemeObject>[]\n): ThemeObject => {\n  if (!sources.length) {\n    return target;\n  }\n  // making sure to not change target (immutable)\n  const output = { ...target };\n  sources.forEach(source => {\n    if (isObject(source)) {\n      Object.keys(source).forEach(key => {\n        if (isObject(source[key])) {\n          if (!output[key]) {\n            output[key] = { ...source[key] };\n          } else {\n            output[key] = deepMerge(\n              output[key] as ThemeObject,\n              source[key] as ThemeObject,\n            );\n          }\n        } else {\n          output[key] = source[key];\n        }\n      });\n    }\n  });\n  return output;\n};\n\nexport const parseMetricToNum = (string = '') =>\n  parseFloat(string.match(/\\d+(\\.\\d+)?/)?.[0] || '0');\n\ninterface CalculatePadParams {\n  value: number;\n  iconDimension: number;\n}\n\nconst calculatePad = ({ value, iconDimension }: CalculatePadParams): string =>\n  `${(value - iconDimension) / 2}px`;\n\ninterface IconPadProps {\n  height?: string;\n  size?: string;\n  width?: string;\n}\n\n// useIconPad applies padding to icon to ensure it aligns\n// with text line-height or desired width\nexport function useIconPad(props: IconPadProps): string {\n  const { height, size = 'medium', width } = props;\n  const theme = useContext(ThemeContext);\n  const iconDimension = parseMetricToNum(theme?.icon?.size?.[size] || size);\n\n  let style = '';\n  // browser default is 16px, but accommodate if app has modified\n  // include fallback in case window is undefined\n  const FALLBACK = '16px';\n  let rootFontSize = parseMetricToNum(FALLBACK);\n  if (typeof window !== 'undefined') {\n    rootFontSize = parseMetricToNum(\n      window?.getComputedStyle(document.body).getPropertyValue('font-size') ||\n        FALLBACK,\n    );\n  }\n  if (height && theme?.text?.[height]?.height) {\n    // the unit on theme text\n    const [unit] = theme.text[height].height.match(\n      /(px|rem)/,\n    ) as RegExpMatchArray;\n    let lineHeight = parseMetricToNum(theme.text[height].height);\n    if (unit === 'rem') lineHeight *= rootFontSize;\n\n    if (lineHeight > iconDimension) {\n      const pad = calculatePad({ value: lineHeight, iconDimension });\n      style += `padding-top: ${pad}; padding-bottom: ${pad};`;\n    }\n  }\n\n  if (width && theme?.text?.[width]?.height) {\n    // the unit on theme text\n    const [unit] = theme.text[width].height.match(\n      /(px|rem)/,\n    ) as RegExpMatchArray;\n    let desiredWidth = parseMetricToNum(theme.text[width].height);\n    if (unit === 'rem') desiredWidth *= rootFontSize;\n\n    if (desiredWidth > iconDimension) {\n      const pad = calculatePad({ value: desiredWidth, iconDimension });\n      style += `padding-left: ${pad}; padding-right: ${pad};`;\n    }\n  }\n\n  return style;\n}\n\n// ensure icons that rely on urls don't have id collision\n// Date.now + Math.random is unique enough for icon use cases\nexport const generatePrefix = (name: string) =>\n  `_grommeticons-${name}-${\n    // don't include time-based/random id generation in snapshot tests to avoid\n    // needing to update snapshots with every commit\n    process.env.NODE_ENV !== 'test' ? Date.now() + Math.random() : ''\n  }`;\n\nexport default {\n  deepMerge,\n  isObject,\n  parseMetricToNum,\n  useIconPad,\n};\n"],"names":["parseMetricToNum","string","parseFloat","match","calculatePad","value","iconDimension","useIconPad","props","height","size","width","theme","useContext","ThemeContext","icon","style","FALLBACK","rootFontSize","window","getComputedStyle","document","body","getPropertyValue","text","unit","lineHeight","pad","desiredWidth"],"mappings":"wIAmDaA,iBAAmB,CAACC,EAAS,KACxCC,WAAWD,EAAOE,MAAM,iBAAiB,IAAM,KAO3CC,aAAe,EAAGC,QAAOC,oBACzBD,EAAQC,GAAiB,EAA7B,kEAUK,SAASC,WAAWC,GACzB,MAAMC,OAAEA,EAAAC,KAAQA,EAAO,SAAAC,MAAUA,GAAUH,EACrCI,EAAQC,EAAAA,WAAWC,gBACnBR,EAAgBN,iBAAiBY,GAAOG,MAAML,OAAOA,IAASA,GAEpE,IAAIM,EAAQ,GAGZ,MAAMC,EAAW,OACjB,IAAIC,EAAelB,iBAAiBiB,GAOpC,GANsB,oBAAXE,SACTD,EAAelB,iBACbmB,QAAQC,iBAAiBC,SAASC,MAAMC,iBAAiB,cACvDN,IAGFR,GAAUG,GAAOY,OAAOf,IAASA,OAAQ,CAE3C,MAAOgB,GAAQb,EAAMY,KAAKf,GAAQA,OAAON,MACvC,YAEF,IAAIuB,EAAa1B,iBAAiBY,EAAMY,KAAKf,GAAQA,QAGrD,GAFa,QAATgB,IAAgBC,GAAcR,GAE9BQ,EAAapB,EAAe,CAC9B,MAAMqB,EAAMvB,aAAa,CAAEC,MAAOqB,EAAYpB,kBAC9CU,GAAS,gBAAgBW,sBAAwBA,IACnD,CACF,CAEA,GAAIhB,GAASC,GAAOY,OAAOb,IAAQF,OAAQ,CAEzC,MAAOgB,GAAQb,EAAMY,KAAKb,GAAOF,OAAON,MACtC,YAEF,IAAIyB,EAAe5B,iBAAiBY,EAAMY,KAAKb,GAAOF,QAGtD,GAFa,QAATgB,IAAgBG,GAAgBV,GAEhCU,EAAetB,EAAe,CAChC,MAAMqB,EAAMvB,aAAa,CAAEC,MAAOuB,EAActB,kBAChDU,GAAS,iBAAiBW,qBAAuBA,IACnD,CACF,CAEA,OAAOX,CACT"}