{"version":3,"file":"iconPicker.mjs","names":[],"sources":["../../../../package/common/iconPicker/iconPicker.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './iconPicker.module.pcss';\nimport Ripple from '../ripple';\nimport type { RippleHandle } from '../ripple';\nimport type { IconPickerItem, IconPickerProps } from './iconPicker.types';\n\nfunction hasError(props: IconPickerProps): boolean {\n  const { formValidator } = props;\n  return formValidator ? formValidator.shouldShowError : false;\n}\n\nfunction isRequired(props: IconPickerProps): boolean {\n  const { isRequired: reqProp, formValidator } = props;\n  return !!(\n    reqProp || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n  );\n}\n\nexport default function IconPicker({\n  data = [],\n  selectedId = null,\n  label = '',\n  onChange,\n  formValidator = null,\n  isRequired: _isRequired,\n  className,\n  style,\n  classNames,\n  styles: slotStyles,\n  ...rest\n}: IconPickerProps) {\n  const currentValue = formValidator ? ((formValidator.value as string) ?? null) : selectedId;\n  const showError = hasError({ formValidator, isRequired: _isRequired });\n  const required = isRequired({ formValidator, isRequired: _isRequired });\n\n  const itemRefs = useRef<(HTMLDivElement | null)[]>([]);\n  const rippleRefs = useRef<(RippleHandle | null)[]>([]);\n  const selectedIndex = data.findIndex((item) => item.id === currentValue);\n  const rovingIndex = selectedIndex >= 0 ? selectedIndex : 0;\n\n  function handleSelect(id: string) {\n    if (formValidator) formValidator.set(id);\n    onChange?.(id);\n  }\n\n  function moveTo(step: 1 | -1, fromIndex: number) {\n    if (data.length === 0) return;\n    const next = (fromIndex + step + data.length) % data.length;\n    itemRefs.current[next]?.focus();\n    handleSelect(data[next].id);\n  }\n\n  function handleKeyDown(event: React.KeyboardEvent, index: number, id: string) {\n    switch (event.key) {\n      case 'ArrowDown':\n      case 'ArrowRight':\n        event.preventDefault();\n        moveTo(1, index);\n        break;\n      case 'ArrowUp':\n      case 'ArrowLeft':\n        event.preventDefault();\n        moveTo(-1, index);\n        break;\n      case ' ':\n      case 'Enter':\n        event.preventDefault();\n        // No DOM click is dispatched here, so Ripple's own listener never sees the activation.\n        rippleRefs.current[index]?.addRipple();\n        handleSelect(id);\n        break;\n      default:\n        break;\n    }\n  }\n\n  return (\n    <div\n      {...rest}\n      className={cx(styles.iconPicker, { [styles.iconPickerError]: showError }, classNames?.root, className)}\n      style={{ ...slotStyles?.root, ...style }}\n    >\n      {label && (\n        <div className={cx(styles.iconPickerLabel, classNames?.label)} style={slotStyles?.label}>\n          {label}\n          {required && ' *'}\n        </div>\n      )}\n      <div\n        role='radiogroup'\n        aria-label={label || undefined}\n        className={cx(styles.iconPickerItemContainer, classNames?.itemContainer)}\n        style={slotStyles?.itemContainer}\n      >\n        {data.map(({ id, label: itemLabel, icon, customIcon }: IconPickerItem, index) => {\n          const checked = currentValue === id;\n          return (\n            <div\n              key={id}\n              ref={(el) => {\n                itemRefs.current[index] = el;\n              }}\n              className={cx(styles.iconPickerItem, { [styles.iconPickerItemSelected]: checked }, classNames?.item)}\n              style={slotStyles?.item}\n              title={itemLabel}\n              tabIndex={index === rovingIndex ? 0 : -1}\n              role='radio'\n              aria-checked={checked}\n              onClick={() => handleSelect(id)}\n              onKeyDown={(event) => handleKeyDown(event, index, id)}\n            >\n              {icon && <FontAwesomeIcon icon={icon} />}\n              {customIcon ?? null}\n              <Ripple\n                ref={(el) => {\n                  rippleRefs.current[index] = el;\n                }}\n              />\n            </div>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n"],"mappings":"oQAQA,SAAS,EAAS,EAAiC,CACjD,GAAM,CAAE,iBAAkB,EAC1B,OAAO,EAAgB,EAAc,gBAAkB,EACzD,CAEA,SAAS,EAAW,EAAiC,CACnD,GAAM,CAAE,WAAY,EAAS,iBAAkB,EAC/C,MAAO,CAAC,EACN,GAAW,GAAe,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,EAE/G,CAEA,SAAwB,EAAW,CACjC,OAAO,CAAC,EACR,aAAa,KACb,QAAQ,GACR,WACA,gBAAgB,KAChB,WAAY,EACZ,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACe,CAClB,IAAM,EAAe,EAAkB,EAAc,OAAoB,KAAQ,EAC3E,EAAY,EAAS,CAAE,gBAAe,WAAY,CAAY,CAAC,EAC/D,EAAW,EAAW,CAAE,gBAAe,WAAY,CAAY,CAAC,EAEhE,EAAW,EAAkC,CAAC,CAAC,EAC/C,EAAa,EAAgC,CAAC,CAAC,EAC/C,EAAgB,EAAK,UAAW,GAAS,EAAK,KAAO,CAAY,EACjE,EAAc,GAAiB,EAAI,EAAgB,EAEzD,SAAS,EAAa,EAAY,CAC5B,GAAe,EAAc,IAAI,CAAE,EACvC,IAAW,CAAE,CACf,CAEA,SAAS,EAAO,EAAc,EAAmB,CAC/C,GAAI,EAAK,SAAW,EAAG,OACvB,IAAM,GAAQ,EAAY,EAAO,EAAK,QAAU,EAAK,OACrD,EAAS,QAAQ,EAAK,EAAE,MAAM,EAC9B,EAAa,EAAK,EAAK,CAAC,EAAE,CAC5B,CAEA,SAAS,EAAc,EAA4B,EAAe,EAAY,CAC5E,OAAQ,EAAM,IAAd,CACE,IAAK,YACL,IAAK,aACH,EAAM,eAAe,EACrB,EAAO,EAAG,CAAK,EACf,MACF,IAAK,UACL,IAAK,YACH,EAAM,eAAe,EACrB,EAAO,GAAI,CAAK,EAChB,MACF,IAAK,IACL,IAAK,QACH,EAAM,eAAe,EAErB,EAAW,QAAQ,EAAM,EAAE,UAAU,EACrC,EAAa,CAAE,CAInB,CACF,CAEA,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,WAAY,EAAG,EAAO,iBAAkB,CAAU,EAAG,GAAY,KAAM,CAAS,EACrG,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAHzC,SAAA,CAKG,GACC,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,KAAK,EAAG,MAAO,GAAY,MAAlF,SAAA,CACG,EACA,GAAY,IACV,CAEP,CAAA,EAAA,EAAC,MAAD,CACE,KAAK,aACL,aAAY,GAAS,IAAA,GACrB,UAAW,EAAG,EAAO,wBAAyB,GAAY,aAAa,EACvE,MAAO,GAAY,cAElB,SAAA,EAAK,KAAK,CAAE,KAAI,MAAO,EAAW,OAAM,cAA8B,IAAU,CAC/E,IAAM,EAAU,IAAiB,EACjC,OACE,EAAC,MAAD,CAEE,IAAM,GAAO,CACX,EAAS,QAAQ,GAAS,CAC5B,EACA,UAAW,EAAG,EAAO,eAAgB,EAAG,EAAO,wBAAyB,CAAQ,EAAG,GAAY,IAAI,EACnG,MAAO,GAAY,KACnB,MAAO,EACP,SAAU,IAAU,EAAc,EAAI,GACtC,KAAK,QACL,eAAc,EACd,YAAe,EAAa,CAAE,EAC9B,UAAY,GAAU,EAAc,EAAO,EAAO,CAAE,EAZtD,SAAA,CAcG,GAAQ,EAAC,EAAD,CAAuB,MAAO,CAAA,EACtC,GAAc,KACf,EAAC,EAAD,CACE,IAAM,GAAO,CACX,EAAW,QAAQ,GAAS,CAC9B,CACD,CAAA,CACE,CApBE,EAAA,CAoBF,CAET,CAAC,CACE,CAAA,CACF,GAET"}