{"version":3,"file":"Tree.cjs","sources":["../../../src/components/Tree/Tree.tsx"],"sourcesContent":["import { useEffect, useMemo } from 'react';\nimport { useClickOutside, useMergedRef } from '@raikou/hooks';\nimport {\n  Box,\n  BoxProps,\n  createVarsResolver,\n  ElementProps,\n  factory,\n  Factory,\n  getSpacing,\n  RaikouSpacing,\n  StylesApiProps,\n  useProps,\n  useStyles,\n} from '../../core';\nimport { TreeNode } from './TreeNode';\nimport { TreeController, useTree } from './use-tree';\nimport { TreeLabelStyle, TreeNodeStyle, TreeRootStyle, TreeSubtreeStyle } from './Tree.css';\n\nexport interface TreeNodeData {\n  label: React.ReactNode;\n  value: string;\n  nodeProps?: Record<string, any>;\n  children?: TreeNodeData[];\n}\n\nexport interface RenderTreeNodePayload {\n  /** Node level in the tree */\n  level: number;\n\n  /** `true` if the node is expanded, applicable only for nodes with `children` */\n  expanded: boolean;\n\n  /** `true` if the node has non-empty `children` array */\n  hasChildren: boolean;\n\n  /** `true` if the node is selected */\n  selected: boolean;\n\n  /** Node data from the `data` prop of `Tree` */\n  node: TreeNodeData;\n\n  /** Tree controller instance, return value of `useTree` hook */\n  tree: TreeController;\n\n  /** Props to spread into the root node element */\n  elementProps: {\n    className: string;\n    style: React.CSSProperties;\n    onClick: (event: React.MouseEvent) => void;\n    'data-selected': boolean | undefined;\n    'data-value': string;\n    'data-hovered': boolean | undefined;\n  };\n}\n\nexport type RenderNode = (payload: RenderTreeNodePayload) => React.ReactNode;\n\nexport type TreeStylesNames = 'root' | 'node' | 'subtree' | 'label';\nexport type TreeCssVariables = {\n  root: '--level-offset';\n};\n\nexport interface TreeProps extends BoxProps, StylesApiProps<TreeFactory>, ElementProps<'ul'> {\n  /** Data used to render nodes */\n  data: TreeNodeData[];\n\n  /** Horizontal padding of each subtree level, key of `theme.spacing` or any valid CSS value, `'lg'` by default */\n  levelOffset?: RaikouSpacing;\n\n  /** Determines whether tree node with children should be expanded on click, `true` by default */\n  expandOnClick?: boolean;\n\n  /** Determines whether tree node with children should be expanded on space key press, `true` by default */\n  expandOnSpace?: boolean;\n\n  /** Determines whether tree node should be checked on space key press, `false` by default */\n  checkOnSpace?: boolean;\n\n  /** Determines whether node should be selected on click, `false` by default */\n  selectOnClick?: boolean;\n\n  /** Use-tree hook instance that can be used to manipulate component state */\n  tree?: TreeController;\n\n  /** A function to render tree node label */\n  renderNode?: RenderNode;\n\n  /** Determines whether selection should be cleared when user clicks outside of the tree, `false` by default */\n  clearSelectionOnOutsideClick?: boolean;\n\n  /** Determines whether tree nodes range can be selected with click when `Shift` key is pressed, `true` by default */\n  allowRangeSelection?: boolean;\n}\n\nfunction getFlatValues(data: TreeNodeData[]): string[] {\n  return data.reduce<string[]>((acc, item) => {\n    acc.push(item.value);\n    if (item.children) {\n      acc.push(...getFlatValues(item.children));\n    }\n    return acc;\n  }, []);\n}\n\nexport type TreeFactory = Factory<{\n  props: TreeProps;\n  ref: HTMLUListElement;\n  stylesNames: TreeStylesNames;\n  vars: TreeCssVariables;\n}>;\n\nconst defaultProps: Partial<TreeProps> = {\n  expandOnClick: true,\n  allowRangeSelection: true,\n  expandOnSpace: true,\n};\n\nconst varsResolver = createVarsResolver<TreeFactory>((_theme, { levelOffset }) => ({\n  root: {\n    '--level-offset': getSpacing(levelOffset),\n  },\n}));\n\nexport const Tree = factory<TreeFactory>((_props, ref) => {\n  const props = useProps('Tree', defaultProps, _props);\n  const {\n    classNames,\n    className,\n    style,\n    styles,\n    unstyled,\n    vars,\n    data,\n    expandOnClick,\n    tree,\n    renderNode,\n    selectOnClick,\n    clearSelectionOnOutsideClick,\n    allowRangeSelection,\n    expandOnSpace,\n    levelOffset,\n    checkOnSpace,\n    ...others\n  } = props;\n\n  const defaultController = useTree();\n  const controller = tree || defaultController;\n\n  const getStyles = useStyles<TreeFactory>({\n    name: 'Tree',\n    classes: {\n      root: TreeRootStyle,\n      subtree: TreeSubtreeStyle,\n      node: TreeNodeStyle,\n      label: TreeLabelStyle,\n    },\n    props,\n    className,\n    style,\n    classNames,\n    styles,\n    unstyled,\n    vars,\n    varsResolver,\n  });\n\n  const clickOutsideRef = useClickOutside(\n    () => clearSelectionOnOutsideClick && controller.clearSelected()\n  );\n\n  const mergedRef = useMergedRef(ref, clickOutsideRef);\n\n  const flatValues = useMemo(() => getFlatValues(data), [data]);\n\n  useEffect(() => {\n    controller.initialize(data);\n  }, [data]);\n\n  const nodes = data.map((node, index) => (\n    <TreeNode\n      key={node.value}\n      node={node}\n      getStyles={getStyles}\n      rootIndex={index}\n      expandOnClick={expandOnClick}\n      selectOnClick={selectOnClick}\n      controller={controller}\n      renderNode={renderNode}\n      flatValues={flatValues}\n      allowRangeSelection={allowRangeSelection}\n      expandOnSpace={expandOnSpace}\n      checkOnSpace={checkOnSpace}\n    />\n  ));\n\n  return (\n    <Box\n      component=\"ul\"\n      ref={mergedRef}\n      {...getStyles('root')}\n      {...others}\n      role=\"tree\"\n      aria-multiselectable={controller.multiple}\n      data-tree-root\n    >\n      {nodes}\n    </Box>\n  );\n});\n\nTree.displayName = '@raikou/core/Tree';\n"],"names":["createVarsResolver","getSpacing","factory","useProps","useTree","useStyles","TreeRootStyle","TreeSubtreeStyle","TreeNodeStyle","TreeLabelStyle","useClickOutside","useMergedRef","useMemo","useEffect","jsx","TreeNode","Box"],"mappings":"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"}