MapKey.svelte 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <script lang="ts">
  2. /**
  3. * The Map's key (design spec §3.6), matching the Screens and Steps views'.
  4. *
  5. * Each row draws the actual stroke or box rather than a word for it — a
  6. * reader matches shapes. Two rows here exist because the Map hides things at
  7. * rest and a picture that hides must say so: the thin links, and the dashed
  8. * back-edges that appear only once a module is selected. A reader who selects
  9. * `src/utils` and watches four maroon dashes appear has no way to guess what
  10. * they are, and the side panel's prose is not where anyone looks for a stroke.
  11. */
  12. interface Props {
  13. /** The weight below which a link waits for a selection. */
  14. minWeight: number;
  15. /** How many links are waiting on one right now; the row is skipped at zero. */
  16. thinCount: number;
  17. /** Whether the vertical order came from declared edges or from raw counts. */
  18. declaredBasis: boolean;
  19. open: boolean;
  20. onToggle: (open: boolean) => void;
  21. }
  22. let { minWeight, thinCount, declaredBasis, open, onToggle }: Props = $props();
  23. </script>
  24. <div class="legend" class:open>
  25. <button class="legend-h" onclick={() => onToggle(!open)} aria-expanded={open}>
  26. Key <span class="dim">{open ? '▾' : '▸'}</span>
  27. </button>
  28. {#if open}
  29. <div class="legend-body">
  30. <div class="lrow">
  31. <span class="k-box mono">src/api</span>
  32. <span>A module — one directory, with the symbols and files in it</span>
  33. </div>
  34. <div class="lrow">
  35. <span class="k-box k-weight mono">src/db</span>
  36. <span>
  37. The bar along the bottom is how much leans on it — files elsewhere that reference
  38. straight into it, against the most depended-on box here. The count is on the box
  39. </span>
  40. </div>
  41. <div class="lrow">
  42. <svg width="44" height="12" aria-hidden="true"><path d="M2 6 H42" class="k-line" /></svg>
  43. <span>
  44. Depends on — the box above calls, imports, extends or names a type from the box below.
  45. Thicker is more references{declaredBasis
  46. ? ''
  47. : '; here the layering had too few imports to trust, so it used raw counts'}
  48. </span>
  49. </div>
  50. <div class="lrow">
  51. <svg width="44" height="12" aria-hidden="true"><path d="M2 6 H42" class="k-line k-back" /></svg>
  52. <span>
  53. Points back up — the lighter half of a mutual dependency, or a link with no import or
  54. declared type behind it. Drawn only while a module it touches is selected
  55. </span>
  56. </div>
  57. <div class="lrow">
  58. <span class="k-label">top / bottom</span>
  59. <span>
  60. A module sits one layer above everything it depends on, so entry points end up at the top
  61. and the foundations — which depend on nothing below — at the bottom
  62. </span>
  63. </div>
  64. <div class="lrow">
  65. <span class="k-box k-sel mono">src/api</span>
  66. <span>Selected: click a module to bring out its links and list its files; everything more than one hop away fades</span>
  67. </div>
  68. <div class="lrow">
  69. <span class="k-label">nothing depends on this</span>
  70. <span>No link in the index arrives here — a script, a workflow, an unreferenced corner</span>
  71. </div>
  72. <div class="lrow">
  73. <span class="k-box k-test mono">__tests__</span>
  74. <span>More than half its files are tests; off unless you turn tests on</span>
  75. </div>
  76. <div class="lrow">
  77. <span class="k-box k-gen mono">gen</span>
  78. <span>Every file in it is tool-generated — nobody wrote it and nobody edits it</span>
  79. </div>
  80. {#if thinCount > 0}
  81. <div class="lrow">
  82. <span class="k-label">{thinCount} hidden</span>
  83. <span>
  84. Links carrying fewer than {minWeight} references wait until you select a module they
  85. touch, so a weak coincidence never draws as a dependency
  86. </span>
  87. </div>
  88. {/if}
  89. </div>
  90. {/if}
  91. </div>
  92. <style>
  93. .legend {
  94. position: absolute;
  95. left: 12px;
  96. bottom: 12px;
  97. z-index: 4;
  98. max-width: 400px;
  99. border: 1px solid var(--rule);
  100. background: var(--paper);
  101. font-size: 11.5px;
  102. color: var(--ink-2);
  103. }
  104. .legend-h {
  105. display: block;
  106. width: 100%;
  107. border: 0;
  108. background: transparent;
  109. padding: 5px 10px;
  110. text-align: left;
  111. color: var(--ink);
  112. font: 600 12px var(--sans);
  113. cursor: pointer;
  114. }
  115. .legend-body {
  116. padding: 2px 10px 8px;
  117. border-top: 1px solid var(--rule-soft);
  118. }
  119. .lrow {
  120. display: flex;
  121. align-items: center;
  122. gap: 10px;
  123. padding: 3px 0;
  124. }
  125. .lrow > :first-child {
  126. flex: 0 0 52px;
  127. display: inline-flex;
  128. justify-content: center;
  129. }
  130. .k-line {
  131. stroke: var(--ink);
  132. stroke-opacity: 0.6;
  133. stroke-width: 1.5;
  134. fill: none;
  135. }
  136. .k-line.k-back {
  137. stroke: var(--accent);
  138. stroke-opacity: 0.8;
  139. stroke-dasharray: 4 3;
  140. }
  141. .k-label {
  142. font-size: 10px;
  143. color: var(--ink-3);
  144. text-align: center;
  145. line-height: 1.2;
  146. }
  147. .k-box {
  148. box-sizing: border-box;
  149. padding: 1px 5px;
  150. border: 1px solid var(--ink);
  151. font-size: 10.5px;
  152. color: var(--ink);
  153. line-height: 14px;
  154. }
  155. /* The bar, drawn the way the canvas draws it: inside the bottom edge. */
  156. .k-box.k-weight {
  157. position: relative;
  158. }
  159. .k-box.k-weight::after {
  160. content: '';
  161. position: absolute;
  162. left: 0;
  163. bottom: 0;
  164. width: 68%;
  165. height: 4px;
  166. background: var(--ink);
  167. opacity: 0.3;
  168. }
  169. /* The same three treatments the canvas uses, at key size. */
  170. .k-box.k-sel {
  171. border-width: 2px;
  172. background: var(--press);
  173. }
  174. .k-box.k-test {
  175. border-style: dashed;
  176. border-color: var(--ink-3);
  177. color: var(--ink-3);
  178. }
  179. .k-box.k-gen {
  180. border-color: var(--ink-4);
  181. color: var(--ink-4);
  182. }
  183. .dim {
  184. color: var(--ink-3);
  185. }
  186. </style>