{"version":3,"file":"CascaderColumns.cjs","names":["getCascaderColumns","CheckIcon","useCascaderSafeArea","UnstyledButton","AccordionChevron","ScrollArea","cascaderOptionHasChildren"],"sources":["../../../src/components/Cascader/CascaderColumns.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport type { GetStylesApi } from '../../core';\nimport { AccordionChevron } from '../Accordion';\nimport { CheckIcon } from '../Checkbox/CheckIcon';\nimport { ScrollArea, ScrollAreaProps } from '../ScrollArea';\nimport { UnstyledButton } from '../UnstyledButton';\nimport type {\n  CascaderOption,\n  CascaderSafeAreaPolygonOptions,\n  CascaderStylesNames,\n} from './Cascader';\nimport { cascaderOptionHasChildren, getCascaderColumns } from './get-cascader-columns';\nimport { useCascaderSafeArea } from './use-cascader-safe-area';\n\ntype CascaderColumnsGetStyles = GetStylesApi<{ props: any; stylesNames: CascaderStylesNames }>;\n\nexport interface CascaderColumnsProps {\n  data: CascaderOption[];\n  activePath: string[];\n  value: string[] | null;\n  keyboardNav: boolean;\n  withCheckIcon: boolean | undefined;\n  checkIconPosition: 'left' | 'right' | undefined;\n  renderOption: ((option: CascaderOption, level: number) => React.ReactNode) | undefined;\n  columnWidth: number | string | undefined;\n  maxDisplayedLevels: number | undefined;\n  previousLevelsControlLabel: string | undefined;\n  nextLevelsControlLabel: string | undefined;\n  maxDropdownHeight: number | string | undefined;\n  nothingFoundMessage: React.ReactNode;\n  getStyles: CascaderColumnsGetStyles;\n  unstyled: boolean | undefined;\n  scrollAreaProps: ScrollAreaProps | undefined;\n  onOptionClick: (level: number, option: CascaderOption) => void;\n  onOptionMouseEnter: (level: number, option: CascaderOption) => void;\n  onColumnsMouseLeave: (() => void) | undefined;\n  onPointerActivity: (() => void) | undefined;\n  listId: string | undefined;\n  safeAreaPolygon: boolean | CascaderSafeAreaPolygonOptions | undefined;\n}\n\nexport function getCascaderOptionId(listId: string | undefined, level: number, value: string) {\n  return listId ? `${listId}-${level}-${value}` : undefined;\n}\n\nexport function CascaderColumns({\n  data,\n  activePath,\n  value,\n  keyboardNav,\n  withCheckIcon,\n  checkIconPosition,\n  renderOption,\n  columnWidth,\n  maxDisplayedLevels,\n  previousLevelsControlLabel,\n  nextLevelsControlLabel,\n  maxDropdownHeight,\n  nothingFoundMessage,\n  getStyles,\n  unstyled,\n  scrollAreaProps,\n  onOptionClick,\n  onOptionMouseEnter,\n  onColumnsMouseLeave,\n  onPointerActivity,\n  listId,\n  safeAreaPolygon,\n}: CascaderColumnsProps) {\n  const allColumns = getCascaderColumns(data, activePath);\n  const totalColumns = allColumns.length;\n  const maxLevels =\n    maxDisplayedLevels && maxDisplayedLevels > 0 ? maxDisplayedLevels : totalColumns;\n  const maxOffset = Math.max(0, totalColumns - maxLevels);\n  const focusedLevel = activePath.length - 1;\n  const showCheckIcon = withCheckIcon !== false;\n\n  // Manual left/right scrolling of the visible window. It is reset synchronously whenever the\n  // active path changes so that the focused column always stays visible during navigation.\n  const activePathKey = JSON.stringify(activePath);\n  const [windowState, setWindowState] = useState({ key: activePathKey, offset: 0 });\n  const windowOffset = windowState.key === activePathKey ? windowState.offset : 0;\n  if (windowState.key !== activePathKey) {\n    setWindowState({ key: activePathKey, offset: 0 });\n  }\n  const setWindowOffset = (updater: (current: number) => number) =>\n    setWindowState((current) => ({ key: activePathKey, offset: updater(current.offset) }));\n\n  const clampedOffset = Math.min(windowOffset, maxOffset);\n  const windowStart = Math.max(0, maxOffset - clampedOffset);\n  const windowEnd = Math.min(totalColumns, windowStart + maxLevels);\n  const visibleColumns = allColumns.slice(windowStart, windowEnd);\n  const hiddenBefore = windowStart;\n  const hiddenAfter = totalColumns - windowEnd;\n\n  const check = showCheckIcon ? <CheckIcon {...getStyles('columnOptionCheck')} /> : null;\n\n  const columnRefs = useRef<Record<number, HTMLDivElement | null>>({});\n  const safeArea = useCascaderSafeArea({ safeAreaPolygon, onFlush: onOptionMouseEnter });\n\n  return (\n    <div\n      {...getStyles('columnsList')}\n      role=\"presentation\"\n      onMouseLeave={() => {\n        safeArea.disarm();\n        onColumnsMouseLeave?.();\n      }}\n      onMouseMove={onPointerActivity}\n    >\n      {hiddenBefore > 0 && (\n        <UnstyledButton\n          {...getStyles('columnsOverflow')}\n          data-position=\"start\"\n          tabIndex={-1}\n          unstyled={unstyled}\n          aria-label={previousLevelsControlLabel}\n          title={previousLevelsControlLabel}\n          onMouseDown={(event) => event.preventDefault()}\n          onClick={() => setWindowOffset((current) => Math.min(maxOffset, current + 1))}\n        >\n          <AccordionChevron />\n        </UnstyledButton>\n      )}\n\n      {visibleColumns.map((options, index) => {\n        const level = windowStart + index;\n        const isLastColumn = index === visibleColumns.length - 1 && hiddenAfter === 0;\n\n        return (\n          <div\n            key={level}\n            ref={(node) => {\n              columnRefs.current[level] = node;\n            }}\n            data-last={isLastColumn || undefined}\n            {...getStyles('column', {\n              style: columnWidth ? { width: columnWidth, minWidth: columnWidth } : undefined,\n            })}\n          >\n            <ScrollArea.Autosize\n              mah={maxDropdownHeight ?? 260}\n              type=\"scroll\"\n              scrollbarSize=\"var(--combobox-padding)\"\n              role=\"listbox\"\n              {...scrollAreaProps}\n              {...getStyles('columnScroll')}\n            >\n              {options.length === 0 ? (\n                <div {...getStyles('columnEmpty')}>{nothingFoundMessage}</div>\n              ) : (\n                options.map((option) => {\n                  const isActive = activePath[level] === option.value;\n                  const isCurrent = isActive && level === focusedLevel && keyboardNav;\n                  // The trail only covers ancestor columns; the deepest column is not highlighted\n                  // during mouse navigation (only via the keyboard \"current\" state)\n                  const isInPath = isActive && level < focusedLevel;\n                  const hasChildren = cascaderOptionHasChildren(option);\n                  const isSelected =\n                    !!value && value.length === level + 1 && value[level] === option.value;\n\n                  return (\n                    <UnstyledButton\n                      key={option.value}\n                      id={getCascaderOptionId(listId, level, option.value)}\n                      role=\"option\"\n                      aria-selected={isCurrent || undefined}\n                      aria-disabled={option.disabled || undefined}\n                      data-active={isCurrent || undefined}\n                      data-in-path={isInPath || undefined}\n                      data-selected={isSelected || undefined}\n                      data-disabled={option.disabled || undefined}\n                      tabIndex={-1}\n                      unstyled={unstyled}\n                      onMouseDown={(event) => event.preventDefault()}\n                      onClick={() => {\n                        if (!option.disabled) {\n                          onOptionClick(level, option);\n                        }\n                      }}\n                      onMouseEnter={() => {\n                        if (option.disabled) {\n                          return;\n                        }\n\n                        if (safeArea.isBlocked(level)) {\n                          safeArea.setPending(level, option);\n                          return;\n                        }\n\n                        onOptionMouseEnter(level, option);\n                      }}\n                      onMouseLeave={(event) => {\n                        safeArea.clearPending(level, option);\n\n                        if (!safeArea.enabled || option.disabled) {\n                          return;\n                        }\n\n                        if (activePath[level] !== option.value) {\n                          return;\n                        }\n\n                        const floating = columnRefs.current[level + 1];\n\n                        if (!floating) {\n                          return;\n                        }\n\n                        safeArea.arm({\n                          level,\n                          reference: event.currentTarget,\n                          floating,\n                          clientX: event.clientX,\n                          clientY: event.clientY,\n                        });\n                      }}\n                      {...getStyles('columnOption')}\n                    >\n                      {isSelected && checkIconPosition === 'left' && check}\n\n                      <span {...getStyles('columnOptionLabel')}>\n                        {renderOption\n                          ? renderOption(option, level)\n                          : (option.label ?? option.value)}\n                      </span>\n\n                      {isSelected && checkIconPosition !== 'left' && check}\n\n                      {hasChildren && (\n                        <span {...getStyles('columnOptionIcon')}>\n                          <AccordionChevron />\n                        </span>\n                      )}\n                    </UnstyledButton>\n                  );\n                })\n              )}\n            </ScrollArea.Autosize>\n          </div>\n        );\n      })}\n\n      {hiddenAfter > 0 && (\n        <UnstyledButton\n          {...getStyles('columnsOverflow')}\n          data-position=\"end\"\n          tabIndex={-1}\n          unstyled={unstyled}\n          aria-label={nextLevelsControlLabel}\n          title={nextLevelsControlLabel}\n          onMouseDown={(event) => event.preventDefault()}\n          onClick={() => setWindowOffset((current) => Math.max(0, current - 1))}\n        >\n          <AccordionChevron />\n        </UnstyledButton>\n      )}\n    </div>\n  );\n}\n\nCascaderColumns.displayName = '@mantine/core/CascaderColumns';\n"],"mappings":"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"}