summaryrefslogtreecommitdiffhomepage
path: root/src/features/plugins/ui/PluginTable.svelte
blob: 717f839330f6c6bd782c59579391c9ff24c1ab31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<script lang="ts">
  import type { PluginNode } from "../logic/types";
  import { tierLabel } from "../logic/types";
  import { groupByTier } from "../logic/view-model";
  import PluginRow from "./PluginRow.svelte";

  let {
    title,
    rows,
    blockReasonFor,
    highlightFor,
    busyIds,
    onToggle,
    onReload,
    onHover,
    onUnhover,
  }: {
    title: string;
    rows: readonly PluginNode[];
    /**
     * Why a row's control is disabled (core-locked / last-provider), or null
     * when interactive. Injected by the manager (it owns the graph context).
     */
    blockReasonFor: (id: string) => string | null;
    /**
     * The §8 hover-highlight state for one row: a highlighted dependency, a
     * highlighted dependent, or none. Injected by the manager (it owns the
     * hovered id + the graph).
     */
    highlightFor: (id: string) => "dep" | "dependent" | null;
    /** Ids with an in-flight mutation (spinner in their controls). */
    busyIds: ReadonlySet<string>;
    onToggle: (node: PluginNode, checked: boolean) => void;
    onReload?: (node: PluginNode) => void;
    onHover: (id: string) => void;
    onUnhover: (id: string) => void;
  } = $props();

  // Tier-grouped rows (Core → Providers → Standard) per the plan-07 decision.
  const groups = $derived(groupByTier(rows));
</script>

<section class="flex flex-col gap-1">
  <h4 class="text-xs font-semibold uppercase opacity-60">{title}</h4>
  {#if rows.length === 0}
    <p class="text-xs opacity-50">Nothing here.</p>
  {:else}
    <table class="table table-sm">
      <thead>
        <tr>
          <th class="w-10">
            <span class="sr-only">Load/unload</span>
          </th>
          <th>Plugin</th>
          <th>Class</th>
          <th>Version</th>
          <th class="text-right">
            <span class="sr-only">Actions</span>
          </th>
        </tr>
      </thead>
      {#each groups as group (group.tier)}
        <tbody>
          <tr>
            <td colspan="5" class="bg-base-200/40 text-xs font-semibold uppercase opacity-60">
              {tierLabel(group.tier)}
            </td>
          </tr>
          {#each group.rows as node (node.id)}
            <PluginRow
              {node}
              highlight={highlightFor(node.id)}
              blockReason={blockReasonFor(node.id)}
              busy={busyIds.has(node.id)}
              {onToggle}
              {...(onReload ? { onReload } : {})}
              {onHover}
              {onUnhover}
            />
          {/each}
        </tbody>
      {/each}
    </table>
  {/if}
</section>