Skip to content
Snippets Groups Projects
TreeList.vue 1.99 KiB
Newer Older
import { computed, ref, watch } from 'vue';
import type { ITreeItem } from '@interfaces/componentsProp';
import TreeItems from '@components/TreeList/TreeItems.vue';
import type { ITLProps } from '@interfaces/componentsProps';
import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common';
interface IStateItem {
  isOpen: boolean;
  label: string;
}

const props = withDefaults(defineProps<ITLProps>(), {
  theme: 'white',
  maxWidth: 300,
const emit = defineEmits(['onClick']);
const items = computed(() => props.items);
const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
const color = computed(() =>
  props.textColor
    ? convertThemeToColor(props.textColor, props.darknessTextColor)
    : convertThemeToTextColor(props.theme, props.darknessTheme),
);
const state = ref<IStateItem[]>([]);
const setItemChildrenToState = (items: ITreeItem[]) => {
  for (const item of items) {
      isOpen: props.expand,
      setItemChildrenToState(item.children);
const setInitialState = () => {
  if (!props?.items) return;
  setItemChildrenToState(props.items);
};
watch(
  [items],
  () => {
    if (items.value) setInitialState();
  },
  {
const toggleIsOpen = (item: ITreeItem) => {
  if (item.isLinkClicked) {
    item.isLinkClicked = false;
    return;
  }
  state.value.map((itemState) => {
    if (itemState.label === item.label) itemState.isOpen = !itemState.isOpen;
  });
  <div
    :style="`background-color: ${themeColor ?? 'white'}; max-width: ${maxWidth}px; padding: 15px 25px 15px 15px`"
    class="tree"
  >
    <TreeItems
      :items="items"
      :state="state"
      :themeColor="themeColor"
      @toggleIsOpen="toggleIsOpen"
      @onClick="emit('onClick')"
    />
  </div>
<style scoped></style>