<script module lang="ts">
  export type FileNode = {
    name: string;
    path: string; // projectPath for file; for folder: virtual path
    kind: 'file' | 'folder';
    children?: FileNode[];
  };
</script>

<script lang="ts">
  import { createEventDispatcher } from 'svelte';

  export let node: FileNode;
  export let activeFilePath: string;
  export let toDisplayPath: (projectPath: string) => string;

  const dispatch = createEventDispatcher<{ open: string }>();
  let open = true;

  function toggle() {
    open = !open;
  }

  function openThis() {
    dispatch('open', node.path);
  }
</script>

{#if node.kind === 'folder'}
  <div class="node folder">
    <button type="button" class="nodeBtn" on:click={toggle}>
      <span class="chev">{open ? '▾' : '▸'}</span>
      <span class="name">{node.name}</span>
    </button>
    {#if open}
      <div class="children">
        {#each node.children ?? [] as child (child.path)}
          <svelte:self node={child} {activeFilePath} {toDisplayPath} on:open />
        {/each}
      </div>
    {/if}
  </div>
{:else}
  <div class="node file">
    <button
      type="button"
      class="nodeBtn"
      class:active={node.path === activeFilePath}
      on:click={openThis}
      title={toDisplayPath(node.path)}
    >
      <span class="dot">•</span>
      <span class="name">{node.name}</span>
    </button>
  </div>
{/if}

<style>
  .node {
    margin: 2px 0;
  }

  .nodeBtn {
    width: 100%;
    appearance: none;
    border: 0;
    background: transparent;
    color: inherit;
    padding: 6px 8px;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
  }

  .nodeBtn:hover {
    background: rgba(255, 255, 255, 0.06);
  }

  .nodeBtn.active {
    background: rgba(255, 255, 255, 0.1);
  }

  .chev {
    width: 14px;
    opacity: 0.75;
  }

  .dot {
    width: 14px;
    opacity: 0.55;
  }

  .children {
    padding-left: 14px;
    border-left: 1px dashed rgba(255, 255, 255, 0.1);
    margin-left: 8px;
  }
</style>
